Jak zwrócić wynik (startActivityForResult) z działania TabHost?


275

W moim przykładzie mam 3 klasy: klasa A, główna aktywność. Klasa A wywołuje startActivityForResult:

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

Klasa B, ta klasa to TabActivity:

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

Klasa C, ta klasa jest normalną działalnością:

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

onActivityResult jest wywoływany w klasie A, ale wynik jest kodem RESULT_CANCELEDzamiast, RESULT_OKa zwrócona wartość zamiaru ma wartość null. Jak mogę zwrócić coś z działania w TabHost?

Zdaję sobie sprawę, że problem polega na tym, że moja klasa C faktycznie działa w klasie B, a klasa B wraca z RESULT_CANCELEDpowrotem do klasy A. Po prostu nie znam jeszcze rozwiązania.

Odpowiedzi:


366

O Boże! Po spędzeniu kilku godzin i pobraniu źródeł Androida wreszcie znalazłem rozwiązanie.

Jeśli spojrzysz na klasę Activity, zobaczysz, że ta finish()metoda odsyła wynik tylko wtedy, gdy mParentustawiono właściwość na null. W przeciwnym razie wynik zostanie utracony.

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);
    }
}

Więc moim rozwiązaniem jest ustawienie wyniku na aktywność nadrzędną, jeśli jest obecna, w ten sposób:

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

Mam nadzieję, że będzie to pomocne, jeśli ktoś ponownie poszuka obejścia tego problemu.


1
Zamieściłem tutaj zhackowane rozwiązanie, jest proste i wymaga przejrzystej aktywności bez zawartości - uzyskuje normalne funkcje cyklu życia i ułatwia wszystko. stackoverflow.com/questions/7812120/...
— CQM

To cudownie! Dziekuję Dziekuję Dziękuję! Działa idealnie i bezproblemowo. Zastąpiłem standardowe metody setResult () dla wszystkich moich działań za pomocą tego małego klejnotu. Dziękuję Ci!
— Scott Biggs,

Użyłem twojego rozwiązania, ale mój kod nie wychwytuje metody onactivityresult po powrocie. pomóżcie mi ... czy muszę użyć czegoś innego?
— skygeek

11
Dlaczego zwracanie wyniku w działaniu nie udokumentowanym nigdzie w przewodnikach API, wydało mi się dziwne.
— alex.p

Cholera! Dobra robota, Illya! Dzięki
— Sirelon

64

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

Z niewielką modyfikacją „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
Proste, setResultbyło najważniejsze. Ustaw to na coś lub na przykład wartość RESULT_OKi możesz już iść; setResult(RESULT_OK);. Pomógł mi, +1
— Afzaal Ahmad Zeeshan

16

Zamiar.FLAG_ACTIVITY_FORWARD_RESULT?

Jeśli jest ustawiony i ten zamiar jest używany do uruchomienia nowej aktywności z istniejącej, cel odpowiedzi dla istniejącej aktywności zostanie przeniesiony do nowej aktywności.


1

Możesz zaimplementować onActivityResult również w klasie B i uruchomić klasę C za pomocą startActivityForResult. Gdy uzyskasz wynik w klasie B, ustaw tam wynik (dla klasy A) na podstawie wyniku z klasy C. Nie wypróbowałem tego, ale myślę, że to powinno zadziałać.

Inną rzeczą, na którą należy zwrócić uwagę, jest to, że Działanie A nie powinno być działaniem typu single Instance. Aby funkcja startActivityForResult działała, klasa B musi być działaniem podrzędnym działania A i nie jest to możliwe w przypadku działania w pojedynczej instancji, nowe działanie (klasa B) rozpoczyna się od nowego zadania.


1
Ponieważ klasa B jest TabActivity, a klasa C to Tab w tym działaniu, nie można wykonać startActivityForResult w klasie B. Żadne z moich działań nie jest działaniem pojedynczym.
— Cameron McBride

-1

Aby rozpocząć działanie 2 od działania 1 i uzyskać wynik, możesz użyć startActivityForResult i zaimplementować onActivityResult w działaniu 1, a następnie użyć setResult w działaniu 2.

Intent intent = new Intent(this, Activity2.class);
intent.putExtra(NUMERO1, numero1);
intent.putExtra(NUMERO2, numero2);
//startActivity(intent);
startActivityForResult(intent, MI_REQUEST_CODE);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.