Wysyłanie danych z powrotem do głównej aktywności w systemie Android

295

Mam dwie czynności: główną i dziecięcą.
Po naciśnięciu przycisku w głównej aktywności uruchamiana jest aktywność podrzędna.

Teraz chcę wysłać niektóre dane z powrotem na ekran główny. Użyłem klasy pakietu, ale to nie działa. Zgłasza pewne wyjątki czasu wykonywania.

Czy jest na to jakieś rozwiązanie?

Rajapandian
źródło
Jeszcze jedna sztuczka pozwala zdefiniować ArrayList w głównej aktywności i ustawić go jako statyczny, aby uzyskać dostęp do drugiej aktywności, a następnie dodać do niej dane, które chcesz wysłać do głównej aktywności, a następnie uzyskać do niej dostęp w głównej aktywności
Abhishek Yadav
Abhishek Yadav, co jeśli twoja główna aktywność zamierza zniszczyć (wywołanie zwrotne onDestroy ()). Myślę, że to niezbyt dobra rada.
Leontsev Anton

Odpowiedzi:

472

Istnieje kilka sposobów na osiągnięcie tego, co chcesz, w zależności od okoliczności.

Najczęstszym scenariuszem (jak brzmi twój) jest sytuacja, w której Aktywność podrzędna jest wykorzystywana w celu uzyskania danych wejściowych od użytkownika - takich jak wybranie kontaktu z listy lub wprowadzenie danych w oknie dialogowym. W takim przypadku należy użyć startActivityForResultdo uruchomienia działania dziecka.

Zapewnia to potok wysyłania danych z powrotem do głównego działania za pomocą setResult. Metoda setResult przyjmuje wartość wyniku int i zamiar, który jest przekazywany z powrotem do działania wywołującego.

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

Aby uzyskać dostęp do zwróconych danych w wywołaniu Aktywność połączenia onActivityResult. RequestCode odpowiada liczbie całkowitej przekazanej w startActivityForResultwywołaniu, podczas gdy wynikCod i dane zamiaru są zwracane z działania potomnego.

@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;
    } 
  }
}
Reto Meier
źródło
4
dla kompletności należy wspomnieć, jakie jest najlepsze miejsce na wywołanie metody kończenia ()? Może to być jasne dla ekspertów, ale dla początkujących dobrze byłoby wiedzieć bez odwoływania się do dodatkowych źródeł.
Califf
1
@jelmoodjasser Trochę czasu zajęło mi zrozumienie, ale w zasadzie, kiedy zaczynasz nową aktywność z Intentem, musisz użyć startActivityForResultfunkcji zamiast po prostu startActivity. Przykładem może być startActivityForResult(myIntent, 2);gdzie 2 to kod wynikowy, który może zastąpić MY_CHILD_ACTIVITYpowyższą instrukcję switch.
uwagi
kiedy drugie działanie zakończy się i powróci do pierwszego działania, to jak ustawić requestCode na drugie działanie przed zakończeniem go ... w celu użycia go do onActivityResult w FirstActivity
Ahamadullah Saikat
Czy zamiar jest obowiązkowy? Jeśli nie mam nic do odesłania, czy potrzebuję pustej intencji, aby odesłać?
Bagus Aji Santoso
@BagusAjiSantoso zamiar jest opcjonalny, potrzebny tylko, jeśli masz coś do odesłania.
Narendra Singh
186

Działanie 1 wykorzystuje startActivityForResult :

startActivityForResult(ActivityTwo, ActivityTwoRequestCode);

Zostanie uruchomione działanie 2 i można wykonać operację. Aby zamknąć działanie, wykonaj następujące czynności:

Intent output = new Intent();
output.putExtra(ActivityOne.Number1Code, num1);
output.putExtra(ActivityOne.Number2Code, num2);
setResult(RESULT_OK, output);
finish();

Ćwiczenie 1 - powrót z poprzedniego działania wywoła 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);
    }
}

AKTUALIZACJA: Odpowiedz na komentarz Seenu69: W ćwiczeniu drugim

int result = Integer.parse(EditText1.getText().toString()) 
           + Integer.parse(EditText2.getText().toString());
output.putExtra(ActivityOne.KEY_RESULT, result);

Następnie w pierwszym ćwiczeniu

int result = data.getExtra(KEY_RESULT);
jimmithy
źródło
Cześć, dziękuję za odpowiedź na moje pytanie. Ten kod mi nie wystarcza. Chcę, aby dodawanie zostało wykonane w samym drugim działaniu, a wynik powinien zostać zwrócony do MainActivity za pomocą metody onActivityResult. Na przykład w głównym działaniu znajduje się tylko przycisk, który powoduje kliknięcie u drugiego działania, widżet editText wprowadza dwie liczby, logika dodawania jest wykonywana w samym drugim działaniu i na koniec wynik jest zwracany do MainActivity. Rozumiem?
Seenu69,
2
W takim przypadku w drugim działaniu należy wykonać obliczenia i zapisać wynik w zamian za pomocą funkcji putExtra (). Zredagowałem moją odpowiedź powyżej
Jimmy
68

Wysyłanie danych z powrotem

Pomaga mi widzieć rzeczy w kontekście. Oto kompletny prosty projekt wysyłania danych z powrotem. Zamiast udostępniać pliki układu XML, oto obraz.

wprowadź opis zdjęcia tutaj

Główna aktywność

  • Rozpocznij drugie działanie startActivityForResult, podając dowolny kod wyniku.
  • Zastąp onActivityResult. Jest to wywoływane po zakończeniu drugiego działania. Możesz upewnić się, że tak naprawdę jest to drugie działanie, sprawdzając kod żądania. (Jest to przydatne, gdy zaczynasz wiele różnych działań od tego samego działania głównego).
  • Wyodrębnij dane, które otrzymałeś ze zwrotu Intent. Dane są wyodrębniane przy użyciu pary klucz-wartość.

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

Druga aktywność

  • Umieść dane, które chcesz wysłać z powrotem do poprzedniej aktywności, w pliku Intent. Dane są przechowywane przy Intentużyciu pary klucz-wartość.
  • Ustaw wynik RESULT_OKi dodaj zamiar przechowywania danych.
  • Zadzwoń, finish()aby zamknąć drugie działanie.

SecondActivity.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();
    }
}

Inne notatki

  • Jeśli jesteś we fragmencie, nie będzie wiedział znaczenia RESULT_OK. Wystarczy użyć pełnej nazwy: Activity.RESULT_OK.

Zobacz też

Suragch
źródło
To jest bardzo dobrze napisane wyraźne wyjaśnienie. Dobra robota!
Kingsley Ijike
29

FirstActivity używa startActivityForResult:

Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent, int resultCode); // suppose resultCode == 2

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 2)
    {
        String message=data.getStringExtra("MESSAGE");
    }
}

W wywołaniu SecondActivity setResult () zdarzenia onClick lub onBackPressed ()

Intent intent=new Intent();
intent.putExtra("MESSAGE",message);
setResult(Activity.RESULT_OK, intent);
Vijay
źródło
Czy to wynikCode żądaniaCode?
Engr Syed Rowshan Ali
15

Wywołaj zamiar działania potomnego za pomocą wywołania metody startActivityForResult ()

Oto przykład: http://developer.android.com/training/notepad/notepad-ex2.html

oraz w „Zwracaniu wyniku z ekranu” tego: http://developer.android.com/guide/faq/commontasks.html#opennewscreen

Zawiłości
źródło
Tak, zgadzam się z cbrulak, link do dokumentów był o wiele bardziej pomocny niż odpowiedź.
george_h
Linki pokazują teraz kilka ogólnych rzeczy. Treść może ulec zmianie, zaktualizuj ją lub usuń odpowiedź dla społeczności
Manoranjan,
7

Dla lepszego odniesienia stworzyłem prostą klasę demonstracyjną.

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

    }
}

A oto 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();

            }
        });

    }
}
Kuls
źródło
3
dobrze wyjaśnione!
Radhey,
5

W pierwszym działaniu możesz wysłać zamiar za pomocą, startActivityForResult()a następnie uzyskać wynik z drugiego działania po jego zakończeniu 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);
            }
        }
    }
}

SecondActivity.class

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();
    }
}
Yogesh Adhe
źródło
1

Wszystkie te odpowiedzi wyjaśniają, że scenariusz drugiego działania musi zostać zakończony po wysłaniu danych.

Ale w przypadku, gdy nie chcesz zakończyć drugiej czynności i chcesz wysłać dane z powrotem do pierwszego, możesz do tego użyć BroadCastReceiver.

W drugiej aktywności -

Intent intent = new Intent("data");
intent.putExtra("some_data", true);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

W pierwszej aktywności

private BroadcastReceiver tempReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // do some action
    }
};

Zarejestruj odbiornik w onCreate () -

 LocalBroadcastManager.getInstance(this).registerReceiver(tempReceiver,new IntentFilter("data"));

Wyrejestruj to w onDestroy ()

Shivam Yadav
źródło
0

Innym sposobem osiągnięcia pożądanego rezultatu, który może być lepszy w zależności od twojej sytuacji, jest stworzenie interfejsu nasłuchiwania.

Nakłaniając działanie rodzica do nasłuchiwania interfejsu uruchamianego przez działanie potomne podczas przekazywania wymaganych danych jako parametru, można stworzyć podobny zestaw okoliczności

Lenos
źródło
-1

Można to zrobić na kilka sposobów. 1. za pomocą metody startActivityForResult (), która jest bardzo dobrze wyjaśniona w powyższych odpowiedziach.

  1. tworząc zmienne statyczne w swojej klasie „Utils” lub dowolnej własnej klasie. Na przykład chcę przekazać studentId z ActivityB do ActivityA.Pierwsze moje ActivityA wywołuje ActivityB. Następnie wewnątrz ActivityB ustaw studentId (który jest polem statycznym w Utils.class). W ten sposób Utils.STUDENT_ID = "1234"; następnie wracając do działania A, użyj studentId zapisanego w Utils.STUDENT_ID.

  2. poprzez utworzenie metody pobierającej i ustawiającej w swojej klasie aplikacji.

lubię to:

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

więc gotowe. wystarczy ustawić dane w środku, gdy jesteś w ActivityB, a po powrocie do ActivityA, pobierz dane.

swetabh suman
źródło
-1

Tylko mały szczegół, który moim zdaniem brakuje w powyższych odpowiedziach.

Jeśli aktywność dziecka można otworzyć z wielu zajęć dla rodziców, możesz sprawdzić, czy musisz to zrobić, setResultczy nie, w zależności od tego, czy Twoje działanie zostało otwarte przez startActivitylub startActivityForResult. Możesz to osiągnąć za pomocą getCallingActivity(). Więcej informacji tutaj .

Dhruv Jagetiya
źródło
-2

Użyj sharedPreferences i zapisz swoje dane i uzyskaj do nich dostęp z dowolnego miejsca w aplikacji

zapisz datę w ten sposób

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putString(key, value);
    editor.commit();

I odbieraj takie dane

SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
    String savedPref = sharedPreferences.getString(key, "");
    mOutputView.setText(savedPref);
Hybrydowy programista
źródło
6
Byłoby to bardziej odpowiednie, gdyby drugim działaniem było ustawienie stałej zmiany / ustawienia w aplikacji.
elimirks
Czy to zadziała, jeśli chcę udostępniać dane między 2 różnymi aplikacjami na Androida? Jedna z nich nazywana biblioteką?
joey rohan
21
To jest nadużycie dotyczące SharedPreferences.
Eran Goldin
1
Użycie tej metody do przekazywania danych między dwoma działaniami (pierwotne pytanie OP) jest jak nadużywanie SharedPreferences. Nie jest to do tego przeznaczone, a system musi wykonać zbyt wiele pracy (zapisanie xml na pamięci i ponowne odczytanie go), aby wykonać proste zadanie, takie jak przekazywanie danych między dwiema czynnościami.
Sudara