Come restituire un risultato (startActivityForResult) da un'attività TabHost?


275

Nel mio esempio ho 3 classi: Classe A, l'attività principale. La classe A chiama startActivityForResult:

Intent intent = new Intent(this, ClassB.class);
startActivityForResult(intent, "STRING");

Classe B, questa classe è un TabActivity:

Intent intent = new Intent(this, ClassC.class);
tabHost.addTab...

Classe C, questa classe è un'attività normale:

Intent intent = this.getIntent();
intent.putExtra("SOMETHING", "EXTRAS");
this.setResult(RESULT_OK, intent);
finish();

onActivityResult viene chiamato nella classe A, ma il risultatoCode è RESULT_CANCELEDinvece RESULT_OKe l'intento restituito è nullo. Come posso restituire qualcosa dall'attività all'interno di un TabHost?

Mi rendo conto che il problema è che la mia Classe C è effettivamente in esecuzione all'interno della Classe B, e la Classe B è ciò che sta tornando RESULT_CANCELEDalla Classe A. Semplicemente non conosco ancora un lavoro.

Risposte:


366

Oh Dio! Dopo aver trascorso diverse ore e scaricato le fonti Android, sono finalmente arrivato a una soluzione.

Se osservi la classe Activity, vedrai che quel finish()metodo restituisce il risultato solo se c'è una mParentproprietà impostata su null. Altrimenti il ​​risultato è perso.

public void finish() {
    if (mParent == null) {
        int resultCode;
        Intent resultData;
        synchronized (this) {
            resultCode = mResultCode;
            resultData = mResultData;
        }
        if (Config.LOGV) Log.v(TAG, "Finishing self: token=" + mToken);
        try {
            if (ActivityManagerNative.getDefault()
                .finishActivity(mToken, resultCode, resultData)) {
                mFinished = true;
            }
        } catch (RemoteException e) {
            // Empty
        }
    } else {
        mParent.finishFromChild(this);
    }
}

Quindi la mia soluzione è di impostare il risultato sull'attività principale se presente, in questo modo:

Intent data = new Intent();
 [...]
if (getParent() == null) {
    setResult(Activity.RESULT_OK, data);
} else {
    getParent().setResult(Activity.RESULT_OK, data);
}
finish();

Spero che sarà utile se qualcuno cerca nuovamente questo problema.


1
Ho pubblicato una soluzione hacky qui, è semplice e comporta un'attività trasparente senza contenuti: ottiene normali funzioni del ciclo di vita e semplifica tutto. stackoverflow.com/questions/7812120/…
CQM

È fantastico! Grazie, grazie, grazie! Funziona perfettamente e con pochissima confusione. Ho scavalcato i normali metodi setResult () per tutte le mie attività con questo piccolo gioiello. Grazie!
Scott Biggs,

Ho usato la tua soluzione, ma il mio codice non sta rilevando il metodo onactivityresult quando torno. per favore aiutami .. devo usare qualcos'altro?
skygeek il

11
Perché restituire un risultato in un'attività non documentata da nessuna parte nelle guide API, mi è sembrato strano.
alex.p,

Dannazione! Ottimo lavoro, Illya! Grazie
Sirelon

64

http://tylenoly.wordpress.com/2010/10/27/how-to-finish-activity-with-results/

Con una leggera modifica per "param_result"

/* Start Activity */
public void onClick(View v) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setClassName("com.thinoo.ActivityTest", "com.thinoo.ActivityTest.NewActivity");
    startActivityForResult(intent,90);
}
/* Called when the second activity's finished */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch(requestCode) {
    case 90:
        if (resultCode == RESULT_OK) {
            Bundle res = data.getExtras();
            String result = res.getString("param_result");
            Log.d("FIRST", "result:"+result);
        }
        break;
    }
}

private void finishWithResult()
{
    Bundle conData = new Bundle();
    conData.putString("param_result", "Thanks Thanks");
    Intent intent = new Intent();
    intent.putExtras(conData);
    setResult(RESULT_OK, intent);
    finish();
}

2
Semplice, setResultera la cosa principale. Impostalo su qualcosa o su un valore per esempio RESULT_OKe sei a posto; setResult(RESULT_OK);. Mi ha aiutato, +1
Afzaal Ahmad Zeeshan,

16

Intent.FLAG_ACTIVITY_FORWARD_RESULT?

Se impostato e questo intento viene utilizzato per avviare una nuova attività da una esistente, il target di risposta dell'attività esistente verrà trasferito alla nuova attività.


1

È possibile implementare un onActivityResult anche nella classe B e avviare la classe C utilizzando startActivityForResult. Una volta ottenuto il risultato in Classe B, impostare lì il risultato (per la Classe A) in base al risultato della Classe C. Non l'ho provato ma penso che dovrebbe funzionare.

Un'altra cosa da tenere in considerazione è che l'attività A non dovrebbe essere un'attività singleInstance. Affinché startActivityForResult funzioni, la tua Classe B deve essere un'attività secondaria rispetto all'attività A e ciò non è possibile in una singola attività di istanza, la nuova attività (classe B) inizia in una nuova attività.


1
Poiché la Classe B è una TabActivity e la Classe C è una Tab in quell'attività, non è possibile eseguire startActivityForResult nella Classe B. Nessuna delle mie attività sono Attività a istanza singola.
Cameron McBride,

-1

Per avviare l'attività 2 dall'attività 1 e ottenere il risultato, è possibile utilizzare startActivityForResult e implementare onActivityResult in attività 1 e utilizzare setResult in attività2.

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(NUMERO1, numero1);
intent.putExtra(NUMERO2, numero2);
//startActivity(intent);
startActivityForResult(intent, MI_REQUEST_CODE);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.