Отправка данных обратно в Основное действие в Android
У меня есть два вида деятельности: основная деятельность и деятельность детей.
Когда я нажимаю кнопку в основном действии, запускается дочернее действие.
Теперь я хочу отправить некоторые данные обратно на главный экран. Я использовал класс Bundle, но он не работает. Выдает некоторые исключения во время выполнения.
Есть ли решение для этого?
13 ответов
Есть несколько способов добиться того, чего вы хотите, в зависимости от обстоятельств.
Наиболее распространенный сценарий (который звучит как ваш) - это когда дочерняя активность используется для получения пользовательского ввода, например, выбора контакта из списка или ввода данных в диалоговом окне. В этом случае вы должны использовать startActivityForResult
для запуска вашего ребенка.
Это обеспечивает конвейер для отправки данных обратно в основное действие с помощью setResult
, Метод setResult принимает значение результата int и намерение, которое передается обратно в вызывающую активность.
Intent resultIntent = new Intent();
// TODO Add extras or a data URI to this intent as appropriate.
resultIntent.putExtra("some_key", "String data");
setResult(Activity.RESULT_OK, resultIntent);
finish();
Для доступа к возвращенным данным в вызывающем переопределении Activity onActivityResult
, Код запроса соответствует целому числу, переданному в startActivityForResult
вызов, в то время как resultCode и Intent данных возвращаются из дочернего Activity.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case (MY_CHILD_ACTIVITY) : {
if (resultCode == Activity.RESULT_OK) {
// TODO Extract the data returned from the child Activity.
String returnValue = data.getStringExtra("some_key");
}
break;
}
}
}
Упражнение 1 использует startActivityForResult:
startActivityForResult(ActivityTwo, ActivityTwoRequestCode)
Активность 2 запущена, и вы можете выполнить операцию, чтобы закрыть Активность, сделайте это:
Intent output = new Intent();
output.putExtra(ActivityOne.Number1Code, num1);
output.putExtra(ActivityOne.Number2Code, num2);
setResult(RESULT_OK, output);
finish();
Упражнение 1 - возврат из предыдущего занятия вызовет onActivityResult:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ActivityTwoRequestCode && resultCode == RESULT_OK && data != null) {
num1 = data.getIntExtra(Number1Code);
num2 = data.getIntExtra(Number2Code);
}
}
ОБНОВЛЕНИЕ: Ответ на комментарий Seenu69, Во второй деятельности,
int result = Integer.parse(EditText1.getText().toString())
+ Integer.parse(EditText2.getText().toString());
output.putExtra(ActivityOne.KEY_RESULT, result);
Затем в первом упражнении
int result = data.getExtra(KEY_RESULT);
Отправка данных назад
Это помогает мне видеть вещи в контексте. Вот полный простой проект для отправки данных обратно. Вместо того, чтобы предоставлять файлы макета XML, здесь изображение.
Основная деятельность
- Начните второе задание с
startActivityForResult
, предоставляя ему произвольный код результата. - Override
onActivityResult
, Это называется, когда заканчивается второе задание. Вы можете убедиться, что это фактически Второе действие, проверив код запроса. (Это полезно, когда вы запускаете несколько разных действий из одного и того же основного действия.) - Извлеките данные, которые вы получили от возврата
Intent
, Данные извлекаются с использованием пары ключ-значение.
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int SECOND_ACTIVITY_REQUEST_CODE = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// "Go to Second Activity" button click
public void onButtonClick(View view) {
// Start the SecondActivity
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, SECOND_ACTIVITY_REQUEST_CODE);
}
// This method is called when the second activity finishes
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Check that it is the SecondActivity with an OK result
if (requestCode == SECOND_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Get String data from Intent
String returnString = data.getStringExtra("keyName");
// Set text view with string
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(returnString);
}
}
}
}
Второе занятие
- Поместите данные, которые вы хотите отправить обратно в предыдущее действие, в
Intent
, Данные хранятся вIntent
используя пару ключ-значение. - Установите результат в
RESULT_OK
и добавьте намерение, содержащее ваши данные. - Вызов
finish()
закрыть второе задание.
Second Activity.java
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
// "Send text back" button click
public void onButtonClick(View view) {
// Get the text from the EditText
EditText editText = (EditText) findViewById(R.id.editText);
String stringToPassBack = editText.getText().toString();
// Put the String to pass back into an Intent and close this activity
Intent intent = new Intent();
intent.putExtra("keyName", stringToPassBack);
setResult(RESULT_OK, intent);
finish();
}
}
Другие заметки
- Если вы находитесь во фрагменте, он не будет знать значение
RESULT_OK
, Просто используйте полное имя:Activity.RESULT_OK
,
Смотрите также
- Более полный ответ, который включает передачу данных вперед
- Соглашения об именах для ключевой строки
В First Activity используется startActivityForResult:
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, int resultCode); //suppose resultCode == 2;
// Call Back method to get the Message form other Activity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==2)
{
String message=data.getStringExtra("MESSAGE");
}
}
При вызове SecondActivity setResult() для событий щелчка или для backPressed()
Intent intent=new Intent();
intent.putExtra("MESSAGE",message);
setResult(2,intent);
ОБНОВЛЕНИЕ, март 2021 г.
Как и в Activity v1.2.0 и Fragment v1.3.0, новый
Activity Result APIs
были введены.
API-интерфейсы Activity Result предоставляют компоненты для регистрации результата, запуска результата и обработки результата после его отправки системой.
Так что нет необходимости использовать
startActivityForResult
а также
onActivityResult
больше.
Чтобы использовать новый API, вам необходимо создать ActivityResultLauncher в вашей исходной активности, указав обратный вызов, который будет запущен, когда целевая активность завершит работу и вернет нужные данные:
private val intentLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
result.data?.getStringExtra("key1")
result.data?.getStringExtra("key2")
result.data?.getStringExtra("key3")
}
}
а затем, запуская свое намерение всякий раз, когда вам нужно:
intentLauncher.launch(Intent(this, YourActivity::class.java))
И чтобы вернуть данные из целевого действия, вам просто нужно добавить намерение со значениями, которые нужно вернуть в
setResult()
метод:
val data = Intent()
data.putExtra("key1", "value1")
data.putExtra("key2", "value2")
data.putExtra("key3", "value3")
setResult(Activity.RESULT_OK, data)
finish()
Для получения дополнительной информации см . документацию Android.
Вызовите намерение дочернего действия с помощью вызова метода startActivityForResult()
Вот пример этого здесь: http://developer.android.com/training/notepad/notepad-ex2.html
и в "Возвращении результата с экрана" этого: http://developer.android.com/guide/faq/commontasks.html
Я создал простой демонстрационный класс для вашего удобства.
FirstActivity.java
public class FirstActivity extends AppCompatActivity {
private static final String TAG = FirstActivity.class.getSimpleName();
private static final int REQUEST_CODE = 101;
private Button btnMoveToNextScreen;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnMoveToNextScreen = (Button) findViewById(R.id.btnMoveToNext);
btnMoveToNextScreen.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(mIntent, REQUEST_CODE);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQUEST_CODE && data !=null) {
String strMessage = data.getStringExtra("keyName");
Log.i(TAG, "onActivityResult: message >>" + strMessage);
}
}
}
}
А вот и SecondActivity.java,
public class SecondActivity extends AppCompatActivity {
private static final String TAG = SecondActivity.class.getSimpleName();
private Button btnMoveToPrevious;
private EditText editText;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
editText = (EditText) findViewById(R.id.editText);
btnMoveToPrevious = (Button) findViewById(R.id.btnMoveToPrevious);
btnMoveToPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String message = editText.getEditableText().toString();
Intent mIntent = new Intent();
mIntent.putExtra("keyName", message);
setResult(RESULT_OK, mIntent);
finish();
}
});
}
}
В первом упражнении вы можете отправить намерение, используя startActivityForResultand()
а затем получить результат от активности звука после того, как он закончил использовать setResult
,
MainActivity.class
public class MainActivity extends AppCompatActivity {
private static final int SECOND_ACTIVITY_RESULT_CODE = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// "Go to Second Activity" button click
public void onButtonClick(View view) {
// Start the SecondActivity
Intent intent = new Intent(this, SecondActivity.class);
// send intent for result
startActivityForResult(intent, SECOND_ACTIVITY_RESULT_CODE);
}
// This method is called when the second activity finishes
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// check that it is the SecondActivity with an OK result
if (requestCode == SECOND_ACTIVITY_RESULT_CODE) {
if (resultCode == RESULT_OK) {
// get String data from Intent
String returnString = data.getStringExtra("keyName");
// set text view with string
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(returnString);
}
}
}
}
========= второстепенная активность
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
// "Send text back" button click
public void onButtonClick(View view) {
// get the text from the EditText
EditText editText = (EditText) findViewById(R.id.editText);
String stringToPassBack = editText.getText().toString();
// put the String to pass back into an Intent and close this activity
Intent intent = new Intent();
intent.putExtra("keyName", stringToPassBack);
setResult(RESULT_OK, intent);
finish();
}
}
Все эти ответы объясняют, что сценарий вашего второго действия должен быть завершен после отправки данных.
Но в случае, если вы не хотите завершать второе действие и хотите отправить данные обратно сначала, для этого вы можете использовать BroadCastReceiver.
Во втором занятии -
Intent intent = new Intent("data");
intent.putExtra("some_data", true);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
В первом упражнении
private BroadcastReceiver tempReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// do some action
}
};
Зарегистрировать получателя в onCreate()-
LocalBroadcastManager.getInstance(this).registerReceiver(tempReceiver,new IntentFilter("data"));
Отмените регистрацию в onDestroy()
Другой способ достижения желаемого результата, который может быть лучше в зависимости от вашей ситуации, - это создать интерфейс слушателя.
Заставляя родительское действие прослушивать интерфейс, который запускается дочерним действием, при передаче требуемых данных в качестве параметра можно создать аналогичный набор обстоятельств.
Есть несколько способов сделать это. 1. с помощью startActivityForResult(), который очень хорошо объяснен в ответах выше.
создавая статические переменные в вашем классе "Utils" или любом другом вашем собственном классе. Например, я хочу передать studentId из ActivityB в ActivityA. Сначала моя ActivityA вызывает ActivityB. Затем внутри ActivityB установите идентификатор студента (который является статическим полем в Utils.class). Вот так Utils.STUDENT_ID="1234"; затем, возвращаясь к ActivityA, используйте studentId, который хранится в Utils.STUDENT_ID.
создав метод получения и установки в вашем классе приложений.
как это:
public class MyApplication extends Application {
private static MyApplication instance = null;
private String studentId="";
public static MyApplication getInstance() {
return instance;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
}
public void setStudentId(String studentID){
this.studentId=studentID;
}
public String getStudentId(){
return this.studentId;
}
}
так что вы сделали. просто установите данные внутри, когда вы находитесь в ActivityB, и после возвращения в ActivityA получите данные.
Просто маленькая деталь, которая, я думаю, отсутствует в ответах выше.
Если активность вашего ребенка может быть открыта из нескольких родительских действий, вы можете проверить, нужно ли вам setResult
или нет, в зависимости от того, была ли ваша деятельность открыта startActivity
или же startActivityForResult
, Вы можете достичь этого с помощью getCallingActivity()
, Больше информации здесь.
Используйте sharedPreferences и сохраняйте свои данные и получайте к ним доступ из любой точки приложения
сохранить дату, как это
SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(key, value);
editor.commit();
И получать данные, как это
SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
String savedPref = sharedPreferences.getString(key, "");
mOutputView.setText(savedPref);