Jak przesyłać dane między działaniami w aplikacji na Androida?


1348

Mam scenariusz, w którym po zalogowaniu za pośrednictwem strony logowania buttonna każdym z nich nastąpi wylogowanie activity.

Po kliknięciu sign-outprzekażę session idzalogowanego użytkownika do wylogowania. Czy ktoś może poprowadzić mnie, jak zapewnić session iddostępność dla wszystkich activities?

Każda alternatywa dla tej sprawy


14
Korzystałem z funkcji sharepreference, która jest przydatna również do przechowywania danych logowania przy funkcji
pamiętania

To działa dla mnie. stackoverflow.com/a/7325248/2125322 Dzięki Darshan Computing
matasoy


w takich przypadkach spróbuj stworzyć klasę commomUtils z metodą sharedprefereces ... to utrzyma kod w czystości i powiązane dane w jednym miejscu. I z łatwością będziesz mógł wyczyścić określony zestaw danych za pomocą tylko jednej metody wyczyszczenia tego konkretnego
pliku preferencji

Odpowiedzi:


1265

Najłatwiej to zrobić, przekazując identyfikator sesji do działania wylogowania w używanym Intentdo uruchomienia działania:

Intent intent = new Intent(getBaseContext(), SignoutActivity.class);
intent.putExtra("EXTRA_SESSION_ID", sessionId);
startActivity(intent);

Uzyskaj dostęp do zamiaru następnej aktywności:

String sessionId = getIntent().getStringExtra("EXTRA_SESSION_ID");

W docs dla zamiarów ma więcej informacji (zobacz w sekcji „Dodatki”).


ok, jeśli przekażę identyfikator sesji, aby wylogować się przy udanym logowaniu i czy będzie działać na dowolnej stronie aktywności, aby się wylogować, czy ręcznie będę musiał przypisać tę wartość każdej aktywności ?? przy użyciu powyższej procedury?
UMAR,

5
Tak, musisz udostępnić identyfikator sesji dla każdego działania, w którym chcesz zezwolić użytkownikowi na wylogowanie się. Alternatywnie możesz zapisać go w obiekcie aplikacji, ale wtedy będziesz musiał zarządzać stanem sesji (sprawdź, czy jest poprawny przed użyciem itp.).
Erich Douglass,

1
Należy pamiętać, że dokumentacja wskazuje, co następuje: Dodaj rozszerzone dane do celu. Nazwa musi zawierać prefiks pakietu, na przykład aplikacja com.android.contacts użyłaby nazw takich jak „com.android.contacts.ShowAll”.
Serguei Fedorov

1
I do odczytu danych z innych zastosowań AktywnościLong session_ids=getIntent().getExtras().getLong("EXTRA_SESSION_IDS");
Farid

1
Jak możemy przekazywać dane setDatai jaka jest różnica między tymi dwoma podejściami? Który jest lepszy?
Hosein Aqajani

1402

W bieżącej działalności utwórz nową Intent:

String value="Hello world";
Intent i = new Intent(CurrentActivity.this, NewActivity.class);    
i.putExtra("key",value);
startActivity(i);

Następnie w nowym działaniu pobierz te wartości:

Bundle extras = getIntent().getExtras();
if (extras != null) {
    String value = extras.getString("key");
    //The key argument here must match that used in the other activity
}

Użyj tej techniki, aby przekazywać zmienne z jednego działania do drugiego.


58
Tylko informacja dla tych, którzy są tak ślepi jak ja: jeśli w swojej bieżącej aktywności umieścisz liczbę całkowitą, musisz wprowadzić ją do nowej za pośrednictwem extras.getInt("new_variable_name"). Jeśli spróbujesz uzyskać go za pośrednictwem getString()Androida, sprawdź, czy podano int i zwraca null!
bish

4
co jeśli działanie już działa, czy trzeba to zrobić startActivity(i);? Mam na myśli, czy mogę wykonać działanie A wywołać działanie B , a to zwróci dane do działania A ? jestem zdezorientowany?
Francisco Corrales Morales


Wolę zmienną łańcuchową. Zawsze możesz przekonwertować ciąg na liczbę całkowitą lub liczbę zmiennoprzecinkową później.
user914425

140

Dodatek Passing Intent to dobre podejście, jak zauważył Erich.

Obiekt aplikacji jest jednak innym sposobem, a czasem jest łatwiejszy w radzeniu sobie z tym samym stanem w wielu działaniach (w przeciwieństwie do konieczności pobierania / umieszczania go wszędzie) lub obiektami bardziej złożonymi niż operacje podstawowe i ciągi.

Możesz rozszerzyć aplikację, a następnie ustawić / uzyskać cokolwiek tam chcesz i uzyskać do niej dostęp z dowolnego działania (w tej samej aplikacji) za pomocą getApplication () .

Pamiętaj również, że inne podejścia, które możesz zobaczyć, takie jak statyka, mogą być problematyczne, ponieważ mogą prowadzić do wycieków pamięci . Aplikacja pomaga również rozwiązać ten problem.


8
+1 za problem ze statyką. prawdopodobnie czyszczenie można rozwiązać, łącząc singleton z metodą klasy onCreate / onTerminate.
Syd

10
Hej, wiem, że ten wątek był już dawno temu, ale podany link jest teraz ślepym zaułkiem. Czy jest gdziekolwiek mogę znaleźć przykład?
JuiCe

Jak to osiągnąć za pomocą aplikacji? @CharlieCollins
Banee Ishaque K

Oto zaktualizowany przykład tego, z bardzo starej książki :) github.com/charlieCollins/android-in-practice/blob/master/ch07/…
Charlie Collins

@JuiCe Wpis na blogu programistów Androida na temat wycieków pamięci nie jest już nieprawidłowy.
Edric

94

Klasa źródłowa:

Intent myIntent = new Intent(this, NewActivity.class);
myIntent.putExtra("firstName", "Your First Name Here");
myIntent.putExtra("lastName", "Your Last Name Here");
startActivity(myIntent)

Klasa docelowa (klasa NewActivity):

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.view);

    Intent intent = getIntent();

    String fName = intent.getStringExtra("firstName");
    String lName = intent.getStringExtra("lastName");
}

3
Czy intencja może być zerowa? Czy powinniśmy sprawdzić, czy nie jest zerowy?
Micro


85

Musisz tylko wysłać dodatki, dzwoniąc w zamiar.

Lubię to:

Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
intent.putExtra("Variable name", "Value you want to pass");
startActivity(intent);

Teraz OnCreatemetodą SecondActivitymożesz pobrać dodatki w ten sposób.

Jeśli przesłana wartość była wlong :

long value = getIntent().getLongExtra("Variable name which you sent as an extra", defaultValue(you can give it anything));

Jeśli przesłana wartość toString :

String value = getIntent().getStringExtra("Variable name which you sent as an extra");

Jeśli przesłana wartość toBoolean :

Boolean value = getIntent().getBooleanExtra("Variable name which you sent as an extra", defaultValue);

3
Należy pamiętać, że dokumentacja wskazuje, co następuje: Dodaj rozszerzone dane do celu. Nazwa musi zawierać prefiks pakietu, na przykład aplikacja com.android.contacts użyłaby nazw takich jak „com.android.contacts.ShowAll”.
Serguei Fedorov

Jest to kopia najlepiej głosowanej odpowiedzi, która istniała już 2 lata przed tą odpowiedzią, oraz odpowiedzi Sahil Mahajana Mj'a, która jest starsza o 1 rok. Jedyna różnica: przykłady booleani longpobierający, którzy warto komentować IMO, a nie odpowiedź.
Murmel

48

Pomaga mi widzieć rzeczy w kontekście. Oto dwa przykłady.

Przekazywanie danych do przodu

wprowadź opis zdjęcia tutaj

Główna aktywność

  • Wpisz dane, które chcesz wysłać, w zamian za pomocą pary klucz-wartość. Zobacz tę odpowiedź na konwencje nazewnictwa dla klucza.
  • Rozpocznij drugie działanie za pomocą startActivity.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @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) {

        // get the text to pass
        EditText editText = (EditText) findViewById(R.id.editText);
        String textToPass = editText.getText().toString();

        // start the SecondActivity
        Intent intent = new Intent(this, SecondActivity.class);
        intent.putExtra(Intent.EXTRA_TEXT, textToPass);
        startActivity(intent);
    }
}

Druga aktywność

  • Używasz getIntent()tego, Intentaby rozpocząć drugą aktywność. Następnie możesz wyodrębnić dane getExtras()i klucz zdefiniowany w pierwszym działaniu. Ponieważ nasze dane są ciągiem, będziemy ich getStringExtratutaj używać .

SecondActivity.java

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        // get the text from MainActivity
        Intent intent = getIntent();
        String text = intent.getStringExtra(Intent.EXTRA_TEXT);

        // use the text in a TextView
        TextView textView = (TextView) findViewById(R.id.textView);
        textView.setText(text);
    }
}

Przekazywanie danych z powrotem

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 wyniku. (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ść. Mógłbym użyć dowolnego ciągu dla klucza, ale użyję predefiniowanego, Intent.EXTRA_TEXTponieważ wysyłam tekst.

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(Intent.EXTRA_TEXT);

                // 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ść. Zdecydowałem się użyć Intent.EXTRA_TEXTdla mojego klucza.
  • 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(Intent.EXTRA_TEXT, stringToPassBack);
        setResult(RESULT_OK, intent);
        finish();
    }
}

3
Wow, dziękuję! Właśnie tego szukałem. Przy korzystaniu z aparatu lub innych elementów zewnętrznych jest całkiem jasne, że spodziewam się rezultatów, ale nie pomyślałem o tym, aby użyć go wewnętrznie. Jako pierwszy umieściłeś to tak otwarcie.
user3195231,

45

Zaktualizowano Uwaga, że ​​wspomniałem o użyciu SharedPreference . Ma prosty interfejs API i jest dostępny we wszystkich działaniach aplikacji. Ale jest to niezdarne rozwiązanie i stanowi zagrożenie dla bezpieczeństwa, jeśli przekazujesz wrażliwe dane. Najlepiej używać zamiarów. Ma obszerną listę przeciążonych metod, które można wykorzystać do lepszego przenoszenia wielu różnych typów danych między działaniami. Spójrz na intent.putExtra . Ten link dość dobrze prezentuje użycie putExtra.

W przekazywaniu danych między działaniami moim preferowanym podejściem jest stworzenie statycznej metody dla odpowiedniego działania, która zawiera wymagane parametry, aby uruchomić zamiar. Który następnie zapewnia łatwą konfigurację i pobieranie parametrów. Więc może tak wyglądać

public class MyActivity extends Activity {
    public static final String ARG_PARAM1 = "arg_param1";
...
public static getIntent(Activity from, String param1, Long param2...) {
    Intent intent = new Intent(from, MyActivity.class);
        intent.putExtra(ARG_PARAM1, param1);
        intent.putExtra(ARG_PARAM2, param2);
        return intent;
}

....
// Use it like this.
startActivity(MyActvitiy.getIntent(FromActivity.this, varA, varB, ...));
...

Następnie możesz utworzyć zamiar zamierzonego działania i upewnić się, że masz wszystkie parametry. Możesz dostosować fragmenty do. Prosty przykład powyżej, ale masz pomysł.


2
Najbardziej podoba mi się twoja odpowiedź ... Przekazywanie jej celowo oznacza, że ​​prawie wszędzie, gdzie rozpoczynam działanie, musisz pamiętać o dołączeniu sessionId. Umieszczając go w SharedPreferences, możesz uzyskać go w dowolnym momencie z dowolnej aktywności. : 0)
bytebender

@bytebender Wiem, że na odpowiedź jest już trochę za późno, doceniam, że podoba ci się moja oryginalna odpowiedź ze względu na jej prostotę, ale ostrożnie przechowuję identyfikator sesji we wspólnych preferencjach. Jeśli musisz przechowywać go na twardym dysku, użyj szyfrowania. Jeśli możesz korzystać ze struktur uwierzytelniania korzystających z JWT, będą one zawierać odświeżacze, które są bezpieczniejsze dla przechowywania długoterminowego, a następnie zachowają token bieżącej sesji jako własność publiczną niestandardowego obiektu aplikacji, aby łatwo uzyskać dostęp do tokenów uwierzytelnienia i zmniejszyć obciążenie związane z aktywnością podpisy celowe.
angryITguy

38

Spróbuj wykonać następujące czynności:

Utwórz prostą klasę „pomocnika” (fabryka dla swoich zamiarów), jak poniżej:

import android.content.Intent;

public class IntentHelper {
    public static final Intent createYourSpecialIntent(Intent src) {
          return new Intent("YourSpecialIntent").addCategory("YourSpecialCategory").putExtras(src);
    }
}

To będzie fabryka dla wszystkich twoich zamiarów. Za każdym razem, gdy potrzebujesz nowej intencji, utwórz statyczną metodę fabryczną w IntentHelper. Aby utworzyć nową intencję, powinieneś po prostu powiedzieć to w ten sposób:

IntentHelper.createYourSpecialIntent(getIntent());

W twojej działalności Jeśli chcesz „zapisać” niektóre dane w „sesji”, skorzystaj z następujących opcji:

IntentHelper.createYourSpecialIntent(getIntent()).putExtra("YOUR_FIELD_NAME", fieldValueToSave);

I wyślij ten zamiar. W działaniu docelowym twoje pole będzie dostępne jako:

getIntent().getStringExtra("YOUR_FIELD_NAME");

Więc teraz możemy używać Intent jak tej samej starej sesji (jak w serwletach lub JSP ).


28

Możesz także przekazywać obiekty klasy niestandardowej, tworząc klasę paczkowalną . Najlepszym sposobem na uczynienie go paczkowym jest napisanie swojej klasy, a następnie po prostu wklejenie jej do strony takiej jak http://www.parcelabler.com/ . Kliknij kompilację, a otrzymasz nowy kod. Skopiuj wszystko i zastąp oryginalną zawartość klasy. Następnie-

Intent intent = new Intent(getBaseContext(), NextActivity.class);
Foo foo = new Foo();
intent.putExtra("foo", foo);
startActivity(intent);

i uzyskaj wynik w NextActivity jak-

Foo foo = getIntent().getExtras().getParcelable("foo");

Teraz możesz po prostu użyć obiektu foo, tak jak byś tego użył.


23

Innym sposobem jest użycie publicznego pola statycznego, w którym przechowujesz dane, tj .:

public class MyActivity extends Activity {

  public static String SharedString;
  public static SomeObject SharedObject;

//...

5
Naprawdę zastanawiam się, dlaczego twoja sugestia nie uzyskała głosów, jest prostsza i bardziej praktyczna.
Porizm

7
um ... czy to nie narusza zasad OO?
Christian Vielma,

2
@ChristianVielma cóż, to bardziej jak szara strefa ... możesz to zrobić na wiele sposobów, dla mnie wygląda to na czyste „ucieczkę”, więc ... to od ciebie (programisty) zależy, czy podejmie decyzję działa dobrze dla Ciebie lub nie, podoba mi się ten sposób, ponieważ łatwiej jest go śledzić, ale może bardzo szybko się bardzo zabrudzić ...
ComputerSaysNo

2
dlaczego mówisz, że to się brudzi? Czy iOS nie przesyła danych między kontrolerami widoku, ustawiając „właściwości” podobne do tego? Jest to o wiele łatwiejsze niż używanie zamiarów
Terry Bu

2
Tak, przekazujesz dane między kontrolerami widoku, ale nie ze statycznymi właściwościami. Problem polega na tym, że nie jest to właściwość żądanej instancji działania. Sposób, w jaki Android uruchamia działania za pomocą startActivity (), nie natychmiast tworzy instancji obiektu i nie pozwala programistom na ustawienie zmiennej instancji. To dość denerwujące ...
Shawn,

20

Najwygodniejszym sposobem przekazywania danych między działaniami jest przekazywanie zamiarów. W pierwszym działaniu, z którego chcesz wysłać dane, dodaj kod,

String str = "My Data"; //Data you want to send
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("name",str); //Here you will add the data into intent to pass bw activites
v.getContext().startActivity(intent);

Powinieneś również zaimportować

import android.content.Intent;

Następnie w następnym Acitvity (SecondActivity) powinieneś pobrać dane z intencji za pomocą następującego kodu.

String name = this.getIntent().getStringExtra("name");

2
Jest to kopia najlepiej głosowanej odpowiedzi, która pojawiła się tam jeszcze przez 1 rok.
Murmel

19

Możesz użyć SharedPreferences...

  1. Logowanie. Identyfikator sesji magazynu czasu wSharedPreferences

    SharedPreferences preferences = getSharedPreferences("session",getApplicationContext().MODE_PRIVATE);
    Editor editor = preferences.edit();
    editor.putString("sessionId", sessionId);
    editor.commit();
  2. Wyloguj się. Identyfikator sesji pobierania czasu we wspólnych preferencjach

    SharedPreferences preferences = getSharedPreferences("session", getApplicationContext().MODE_PRIVATE);
    String sessionId = preferences.getString("sessionId", null);

Jeśli nie masz wymaganego identyfikatora sesji, usuń preferencje udostępnione:

SharedPreferences settings = context.getSharedPreferences("session", Context.MODE_PRIVATE);
settings.edit().clear().commit();

Jest to bardzo przydatne, ponieważ jeden raz zapisujesz wartość, a następnie odzyskujesz dowolne miejsce aktywności.


17

Standardowe podejście.

Intent i = new Intent(this, ActivityTwo.class);
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.autocomplete);
String getrec=textView.getText().toString();
Bundle bundle = new Bundle();
bundle.putString(“stuff”, getrec);
i.putExtras(bundle);
startActivity(i);

Teraz w drugiej aktywności pobierz dane z pakietu:

Zdobądź pakiet

Bundle bundle = getIntent().getExtras();

Wyodrębnij dane…

String stuff = bundle.getString(“stuff”); 

1
Duplikat, jak już zaproponował PRABEESH RK w 2012 roku. Można go ograniczyć do i.putExtras()/, getIntent().getString()który jest proponowany przez 6 innych odpowiedzi ...
Murmel,

17

Z działalności

 int n= 10;
 Intent in = new Intent(From_Activity.this,To_Activity.class);
 Bundle b1 = new Bundle();
 b1.putInt("integerNumber",n);
 in.putExtras(b1);
 startActivity(in);

Do działania

 Bundle b2 = getIntent().getExtras();
 int m = 0;
 if(b2 != null)
  {
     m = b2.getInt("integerNumber");
  }

1
Duplikat: BundlePodejście oparte zostało już zaproponowane przez PRABEESH RK w 2012 r. I Ajay Venugopal , Krishna . I może być zredukowany do i.putExtras()/, getIntent().getString()który jest proponowany przez 8 innych odpowiedzi ...
Murmel,

11

Możesz wysyłać dane między działaniami za pomocą obiektu docelowego. Rozważ, że masz dwie czynności, mianowicie FirstActivityi SecondActivity.

Inside FirstActivity:

Za pomocą zamiaru:

i = new Intent(FirstActivity.this,SecondActivity.class);
i.putExtra("key", value);
startActivity(i)

Inside SecondActivity

Bundle bundle= getIntent().getExtras();

Teraz możesz używać różnych metod klas pakietów, aby uzyskać wartości przekazywane z FirstActivity według klucza.

Np bundle.getString("key"), bundle.getDouble("key"), bundle.getInt("key")itd.


1
Duplikat: BundlePodejście oparte zostało już zaproponowane przez PRABEESH RK w 2012 r. I Ajay Venugopal . I może być zredukowany do i.putExtras()/, getIntent().getString()który jest proponowany przez 7 innych odpowiedzi ...
Murmel

11

Jeśli chcesz przenieść bitmapę między Aktywnościami / Fragmentami


Czynność

Aby przekazać bitmapę między Aktywnościami

Intent intent = new Intent(this, Activity.class);
intent.putExtra("bitmap", bitmap);

I w klasie Activity

Bitmap bitmap = getIntent().getParcelableExtra("bitmap");

Fragment

Aby przekazać bitmapę między fragmentami

SecondFragment fragment = new SecondFragment();
Bundle bundle = new Bundle();
bundle.putParcelable("bitmap", bitmap);
fragment.setArguments(bundle);

Aby otrzymać wewnątrz SecondFragment

Bitmap bitmap = getArguments().getParcelable("bitmap");

Przesyłanie dużych bitmap

Jeśli otrzymujesz nieudaną transakcję wiążącą, oznacza to, że przekraczasz bufor transakcji wiążącej, przenosząc duży element z jednego działania do drugiego.

W takim przypadku musisz skompresować mapę bitową jako tablicę bajtów, a następnie rozpakować ją w innej czynności , takiej jak ta

W FirstActivity

Intent intent = new Intent(this, SecondActivity.class);

ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPG, 100, stream);
byte[] bytes = stream.toByteArray(); 
intent.putExtra("bitmapbytes",bytes);

I w SecondActivity

byte[] bytes = getIntent().getByteArrayExtra("bitmapbytes");
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

9
Intent intent = new Intent(YourCurrentActivity.this, YourActivityName.class);
intent.putExtra("NAme","John");
intent.putExtra("Id",1);
startActivity(intent);

Możesz odzyskać go w innym działaniu. Dwie drogi:

int id = getIntent.getIntExtra("id", /* defaltvalue */ 2);

Drugi sposób to:

Intent i = getIntent();
String name = i.getStringExtra("name");


8

Oto moja najlepsza praktyka i bardzo pomaga, gdy projekt jest ogromny i złożony.

Załóżmy, że mam 2 działania, LoginActivityi HomeActivity. Chcę przekazać 2 parametry (nazwa użytkownika i hasło) od LoginActivitydo HomeActivity.

Najpierw tworzę moje HomeIntent

public class HomeIntent extends Intent {

    private static final String ACTION_LOGIN = "action_login";
    private static final String ACTION_LOGOUT = "action_logout";

    private static final String ARG_USERNAME = "arg_username";
    private static final String ARG_PASSWORD = "arg_password";


    public HomeIntent(Context ctx, boolean isLogIn) {
        this(ctx);
        //set action type
        setAction(isLogIn ? ACTION_LOGIN : ACTION_LOGOUT);
    }

    public HomeIntent(Context ctx) {
        super(ctx, HomeActivity.class);
    }

    //This will be needed for receiving data
    public HomeIntent(Intent intent) {
        super(intent);
    }

    public void setData(String userName, String password) {
        putExtra(ARG_USERNAME, userName);
        putExtra(ARG_PASSWORD, password);
    }

    public String getUsername() {
        return getStringExtra(ARG_USERNAME);
    }

    public String getPassword() {
        return getStringExtra(ARG_PASSWORD);
    }

    //To separate the params is for which action, we should create action
    public boolean isActionLogIn() {
        return getAction().equals(ACTION_LOGIN);
    }

    public boolean isActionLogOut() {
        return getAction().equals(ACTION_LOGOUT);
    }
}

Oto jak przekazuję dane w mojej LoginActivity

public class LoginActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        String username = "phearum";
        String password = "pwd1133";
        final boolean isActionLogin = true;
        //Passing data to HomeActivity
        final HomeIntent homeIntent = new HomeIntent(this, isActionLogin);
        homeIntent.setData(username, password);
        startActivity(homeIntent);

    }
}

Ostatni krok, oto jak otrzymuję dane HomeActivity

public class HomeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        //This is how we receive the data from LoginActivity
        //Make sure you pass getIntent() to the HomeIntent constructor
        final HomeIntent homeIntent = new HomeIntent(getIntent());
        Log.d("HomeActivity", "Is action login?  " + homeIntent.isActionLogIn());
        Log.d("HomeActivity", "username: " + homeIntent.getUsername());
        Log.d("HomeActivity", "password: " + homeIntent.getPassword());
    }
}

Gotowy! Fajnie :) Chcę tylko podzielić się swoim doświadczeniem. Jeśli pracujesz nad małym projektem, nie powinien to być duży problem. Ale kiedy pracujesz nad dużym projektem, to naprawdę boli, gdy chcesz dokonać refaktoryzacji lub naprawy błędów.


7

Dodatkowa odpowiedź: konwencje nazewnictwa dla ciągu klucza

Odpowiedzi na faktyczny proces przekazywania danych zostały już udzielone, jednak w większości odpowiedzi użyto zakodowanych ciągów znaków dla nazwy klucza w zamiarze. Zwykle jest to w porządku, gdy jest używane tylko w aplikacji. Jednak dokumentacja zaleca stosowanie EXTRA_*stałych dla standardowych typów danych.

Przykład 1: Używanie Intent.EXTRA_*kluczy

Pierwsza aktywność

Intent intent = new Intent(getActivity(), SecondActivity.class);
intent.putExtra(Intent.EXTRA_TEXT, "my text");
startActivity(intent);

Druga aktywność:

Intent intent = getIntent();
String myText = intent.getExtras().getString(Intent.EXTRA_TEXT);

Przykład 2: Definiowanie własnego static finalklucza

Jeśli jeden z Intent.EXTRA_*Ciągów nie odpowiada Twoim potrzebom, możesz zdefiniować własny na początku pierwszej aktywności.

static final String EXTRA_STUFF = "com.myPackageName.EXTRA_STUFF";

Dołączenie nazwy pakietu to tylko konwencja, jeśli używasz tylko klucza we własnej aplikacji. Konieczne jest jednak unikanie konfliktów nazw, jeśli tworzysz jakąś usługę, którą inne aplikacje mogą wywoływać z zamiarem.

Pierwsza aktywność:

Intent intent = new Intent(getActivity(), SecondActivity.class);
intent.putExtra(EXTRA_STUFF, "my text");
startActivity(intent);

Druga aktywność:

Intent intent = getIntent();
String myText = intent.getExtras().getString(FirstActivity.EXTRA_STUFF);

Przykład 3: Korzystanie z klucza zasobu String

Chociaż nie wspomniano w dokumentacji, ta odpowiedź zaleca użycie zasobu String, aby uniknąć zależności między działaniami.

strings.xml

 <string name="EXTRA_STUFF">com.myPackageName.MY_NAME</string>

Pierwsza aktywność

Intent intent = new Intent(getActivity(), SecondActivity.class);
intent.putExtra(getString(R.string.EXTRA_STUFF), "my text");
startActivity(intent);

Druga aktywność

Intent intent = getIntent();
String myText = intent.getExtras().getString(getString(R.string.EXTRA_STUFF));

7

Możesz użyć Intent

Intent mIntent = new Intent(FirstActivity.this, SecondActivity.class);
mIntent.putExtra("data", data);
startActivity(mIntent);

Innym sposobem może być również użycie wzorca singletonu :

public class DataHolder {

 private static DataHolder dataHolder;
 private List<Model> dataList;

 public void setDataList(List<Model>dataList) {
    this.dataList = dataList;
 }

 public List<Model> getDataList() {
    return dataList;
 }

 public synchronized static DataHolder getInstance() {
    if (dataHolder == null) {
       dataHolder = new DataHolder();
    }
    return dataHolder;
 }
}

Z Twojej FirstActivity

private List<Model> dataList = new ArrayList<>();
DataHolder.getInstance().setDataList(dataList);

Na SecondActivity

private List<Model> dataList = DataHolder.getInstance().getDataList();

Duplikat: Intencją podejście jest już proponowany przez szczycie najbardziej głosowało odpowiedź i odpowiedź sahil Mahajan MJ i odpowiedzi Mayank Saini za i odpowiedzi Md Rahmana. , Odpowiedź Dilavar M. , odpowiedź Android dewelopera , sahulab . Singleton: Odpowiedź Rodiona Altshulera
Murmel,

6

Przekazywanie danych między czynnościami odbywa się głównie za pomocą obiektu celowego.

Najpierw musisz dołączyć dane do obiektu docelowego za pomocą Bundleklasy. Następnie wywołaj działanie przy użyciu jednej z metod startActivity()lub startActivityForResult().

Możesz znaleźć więcej informacji na ten temat, na przykład z wpisu na blogu Przekazywanie danych do działania .


Jest to mniej więcej to samo, co bezpośrednie korzystanie z dostarczonych metod Intent ( Intent#putExtra()). Ale dodaje kolejny Bundlei komplikuje sprawy.
Murmel

6

Możesz wypróbować Preferencje wspólne, może to być dobra alternatywa dla udostępniania danych między działaniami

Aby zapisać identyfikator sesji -

SharedPreferences pref = myContexy.getSharedPreferences("Session 
Data",MODE_PRIVATE);
SharedPreferences.Editor edit = pref.edit();
edit.putInt("Session ID", session_id);
edit.commit();

Aby je zdobyć -

SharedPreferences pref = myContexy.getSharedPreferences("Session Data", MODE_PRIVATE);
session_id = pref.getInt("Session ID", 0);

Duplikat: To podejście zostało już zaproponowane przez Ravi Parsanię w 2014 r.
Murmel

5

Rozpocznij kolejną czynność od tego parametru przekazywania parametrów poprzez Obiekt pakietu

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "xyz@gmail.com");
startActivity(intent);

Pobierz inną aktywność (YourActivity)

String s = getIntent().getStringExtra("USER_NAME");

Jest to odpowiednie dla prostego rodzaju danych. Ale jeśli chcesz przesyłać złożone dane pomiędzy działaniami, najpierw musisz je serializować.

Tutaj mamy model pracownika

class Employee{
    private String empId;
    private int age;
    print Double salary;

    getters...
    setters...
}

Możesz użyć biblioteki Gson lib dostarczonej przez Google do serializacji złożonych danych w ten sposób

String strEmp = new Gson().toJson(emp);
Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("EMP", strEmp);
startActivity(intent);

Bundle bundle = getIntent().getExtras();
String empStr = bundle.getString("EMP");
            Gson gson = new Gson();
            Type type = new TypeToken<Employee>() {
            }.getType();
            Employee selectedEmp = gson.fromJson(empStr, type);

5

Kotlin

Przejdź od pierwszej aktywności

val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("key", "value")
startActivity(intent)

Wejdź w drugą aktywność

val value = getIntent().getStringExtra("key")

Sugestia

Zawsze przechowuj klucze w stałym pliku, aby lepiej zarządzać.

companion object {
    val KEY = "key"
}

4
/*
 * If you are from transferring data from one class that doesn't
 * extend Activity, then you need to do something like this.
 */ 

public class abc {
    Context context;

    public abc(Context context) {
        this.context = context;
    }

    public void something() {
        context.startactivity(new Intent(context, anyone.class).putextra("key", value));
    }
}

4

Charlie Collins dał mi idealną odpowiedź za pomocą Application.class. Nie zdawałem sobie sprawy, że możemy to tak łatwo podklasować. Oto uproszczony przykład z wykorzystaniem niestandardowej klasy aplikacji.

AndroidManifest.xml

Podaj android:nameatrybut, aby użyć własnej klasy aplikacji.

...
<application android:name="MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
....

MyApplication.java

Użyj tego jako globalnego uchwytu referencyjnego. Działa dobrze w ramach tego samego procesu.

public class MyApplication extends Application {
    private MainActivity mainActivity;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    public void setMainActivity(MainActivity activity) { this.mainActivity=activity; }
    public MainActivity getMainActivity() { return mainActivity; }
}

MainActivity.java

Ustaw globalne odwołanie „singleton” do instancji aplikacji.

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((MyApplication)getApplication()).setMainActivity(this);
    }
    ...

}

MyPreferences.java

Prosty przykład, w którym używam głównego działania z innej instancji działania.

public class MyPreferences extends PreferenceActivity
            implements SharedPreferences.OnSharedPreferenceChangeListener {
    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        PreferenceManager.getDefaultSharedPreferences(this)
            .registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        if (!key.equals("autostart")) {
            ((MyApplication)getApplication()).getMainActivity().refreshUI();
        }
    }
}

4

Niedawno wydałem Vapor API , platformę Android o smaku jQuery, która upraszcza wszelkiego rodzaju zadania. Jak wspomniano, SharedPreferencesjest to jeden ze sposobów, w jaki możesz to zrobić.

VaporSharedPreferencesjest zaimplementowany jako Singleton, więc jest to jedna opcja, a w Vapor API ma mocno przeciążoną .put(...)metodę, więc nie musisz jawnie martwić się o typ danych, który popełniasz - pod warunkiem, że jest obsługiwany. Jest również płynny, więc możesz łączyć połączenia:

$.prefs(...).put("val1", 123).put("val2", "Hello World!").put("something", 3.34);

Opcjonalnie automatycznie zapisuje zmiany i ujednolica proces czytania i pisania pod maską, dzięki czemu nie trzeba jawnie pobierać edytora, tak jak w standardowym Androidzie.

Alternatywnie możesz użyć Intent. W interfejsie API Vapor można również użyć .put(...)metody przeciążalności łańcuchowej na VaporIntent:

$.Intent().put("data", "myData").put("more", 568)...

I przekaż to jako dodatek, jak wspomniano w innych odpowiedziach. Możesz pobrać dodatki ze swojego konta Activity, a ponadto, jeśli używasz, jest VaporActivityto zrobione automatycznie, dzięki czemu możesz użyć:

this.extras()

Aby je odzyskać na drugim końcu, w Activityktórym się przełączasz.

Mam nadzieję, że niektórzy są zainteresowani :)


@BaneeIshaqueK tak przepraszam, nie utrzymywałem tego przez jakiś czas. Zaktualizuj link, aby wskazywał bezpośrednio na Github projektu, na wypadek gdyby pomógł. ps. Nie jestem pewien, co myślałem o tej licencji ... przepraszam
Darius

4

Pierwsza aktywność:

Intent intent = new Intent(getApplicationContext(), ClassName.class);
intent.putExtra("Variable name", "Value you want to pass");
startActivity(intent);

Druga aktywność:

String str= getIntent().getStringExtra("Variable name which you sent as an extra");

4

Możesz przesyłać dane między czynnościami w aplikacji na 3 sposoby

  1. Zamiar
  2. SharedPreferences
  3. Podanie

przekazywanie danych w sposób zamierzony ma pewien limit. W przypadku dużej ilości danych można korzystać z udostępniania danych na poziomie aplikacji, a przechowywanie ich w SharedPreference powoduje zwiększenie rozmiaru aplikacji


3

Użyj klasy globalnej:

public class GlobalClass extends Application
{
    private float vitamin_a;


    public float getVitaminA() {
        return vitamin_a;
    }

    public void setVitaminA(float vitamin_a) {
        this.vitamin_a = vitamin_a;
    }
}

Możesz zadzwonić do seterów i autorów tej klasy ze wszystkich innych klas. Zrób to, musisz utworzyć obiekt GlobalClass w każdym Actitity:

GlobalClass gc = (GlobalClass) getApplication();

Następnie możesz zadzwonić na przykład:

gc.getVitaminA()

Przesłaniająca aplikacja - jest to duplikat odpowiedzi
Ktoś
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.