Transmiterea de informații între componente prin intermediul intențiilor

Intențiile pot încapsula anumite informații care pot fi partajate de componentele între care fac legătura (însă unidirecțional, de la componenta care invocă spre componenta invocată!) prin intermediul secțiunii extra care conține un obiect de tip Bundle. Obținerea valorii secțiunii extra corespunzătoare unei intenții poate fi obținute folosind metoda getExtras(), în timp ce specificarea unor informații care vor fi asociate unei intenții poate fi realizată printr-un apel al metodei putExtras().

O activitate copil, lansată în execuție prin intermediul metodei startActivity(), este independentă de activitatea părinte, astfel încât aceasta nu va fi notificată cu privire la terminarea sa. În situațiile în care un astfel de comportament este necesar, activitatea copil va fi pornită de activitatea părinte ca subactivitate care transmite înapoi un rezultat. Acest lucru se realizează prin lansarea în execuție a activității copil prin intermediul metodei startActivityForResult(). În momentul în care este finalizată, va fi invocată automat metoda onActivityResult() de la nivelul activității părinte.

final private static int ANOTHER_ACTIVITY_REQUEST_CODE = 2017;

@Override
protected void onCreate(Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.activity_main);
    Button btn = (Button)findViewById(R.id.open_activity_button);    

    btn.setOnClickListener(new View.OnClickListener() {         
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                intent.putExtra("some_key", someValue);
                // Pornim intent, adaugam un int pe care il vom folosi ca filtru
                // in onActivityResult
                startActivityForResult(intent, ANOTHER_ACTIVITY_REQUEST_CODE);
            }
    });
}
// Aici vom extrage un bundle ce contine datele intoarse de `SecondActivity`
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
  switch(requestCode) {
    case ANOTHER_ACTIVITY_REQUEST_CODE:
      if (resultCode == Activity.RESULT_OK) {
        Bundle data = intent.getExtras();
      }
      break;
      // process other request codes
  }
}

În activitatea copil, înainte de apelul metodei finish(), va trebui transmis activității părinte codul de rezultat (Activity.RESULT_OK, Activity.RESULT_CANCELED sau orice fel de rezultat de tip întreg) și obiectul de tip intenție care conține datele (opțional, în situația în care trebuie întoarse rezultate explicit), ca parametrii ai metodei setResult(). La polul opus, activitatea SecondActivity va prelua datele astfel:

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
  setContentView(R.layout.second_activity);

  /* Get intent from parent */
  Intent intentFromParent = getIntent();
  Bundle data = intentFromParent.getExtras();
  /* data has now some_key which we can use */
  
  /* Return some data to the calling Intent */
  Intent intentToParent = new Intent();
  intent.putExtra("another_key", anotherValue);
  setResult(RESULT_OK, intentToParent);
  finish();

ResultsLauncher API

onActivityResult e deprecated. Google recomandă folosirea ActivityResultsLauncherAPI. Aceasta nouă abordare este mai sigură și mai ușor de gestionat, deoarece elimină necesitatea de a utiliza coduri de cerere hardcoded și simplifică gestionarea callback-urilor pentru rezultatele activității.

Activitatea părinte (MainActivity) În activitatea părinte, înlocuiește startActivityForResult() și onActivityResult() cu utilizarea unui ActivityResultLauncher.

class MainActivity : AppCompatActivity() {
    // Definește un ActivityResultLauncher
    private lateinit var startForResult: ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Inițializează launcher-ul cu un callback pentru rezultat
        startForResult = registerForActivityResult(StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                // Procesează rezultatul aici
                val data: Intent? = result.data
                val someData = data?.getStringExtra("another_key")
                // Folosește `someData` cum este necesar
            }
        }

        val btn = findViewById<Button>(R.id.open_activity_button)
        btn.setOnClickListener {
            val intent = Intent(this, SecondActivity::class.java).apply {
                putExtra("some_key", "someValue")
            }
            // Lansează activitatea copil folosind launcher-ul
            startForResult.launch(intent)
        }
    }
}

Activitatea Copil (SecondActivity)

class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.second_activity)

        // Presupunând că vrei să returnezi rezultatul la un anumit eveniment, de exemplu, la apăsarea unui buton
        val someButton: Button = findViewById(R.id.some_button)
        someButton.setOnClickListener {
            val returnIntent = Intent().apply {
                putExtra("another_key", "anotherValue")
            }
            setResult(RESULT_OK, returnIntent)
            finish()
        }

        // Dacă activitatea se încheie fără a seta explicit un rezultat, poți să nu faci nimic sau să setezi RESULT_CANCELED
    }
}