Отправка данных обратно в Основное действие в 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(), который очень хорошо объяснен в ответах выше.

  1. создавая статические переменные в вашем классе "Utils" или любом другом вашем собственном классе. Например, я хочу передать studentId из ActivityB в ActivityA. Сначала моя ActivityA вызывает ActivityB. Затем внутри ActivityB установите идентификатор студента (который является статическим полем в Utils.class). Вот так Utils.STUDENT_ID="1234"; затем, возвращаясь к ActivityA, используйте studentId, который хранится в Utils.STUDENT_ID.

  2. создав метод получения и установки в вашем классе приложений.

как это:

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);
Другие вопросы по тегам