Jak wysłać obiekt z jednej Aktywności Androida do innej za pomocą Intencji?

849

Jak mogę przekazać obiekt typu niestandardowego z jednego działania do drugiego za pomocąputExtra() metody klasy Intent ?

UMAR
źródło
@UMMA - nie musisz ciągle zaznaczać swoich pytań jako „Community Wiki”. Spójrz tutaj: meta.stackexchange.com/questions/11740/…
Dave Webb
1
@Paresh: podany link jest uszkodzony. czy mógłbyś podać alternatywę?
antiplex
Sprawdź tę odpowiedź. stackoverflow.com/questions/8857546/…
Heitor Colangelo
znalazłem prostą i elegancką metodę stackoverflow.com/a/37774966/6456129
Yessy

Odpowiedzi:

751

Jeśli tylko przepuszczasz przedmioty, to Parcelable został do tego zaprojektowany. Wymaga nieco więcej wysiłku, niż użycie natywnej serializacji Javy, ale jest o wiele szybszy (i mam na myśli sposób, WAY szybszy).

Z dokumentacji prosty przykład implementacji to:

// simple class that just has one member property as an example
public class MyParcelable implements Parcelable {
    private int mData;

    /* everything below here is for implementing Parcelable */

    // 99.9% of the time you can just ignore this
    @Override
    public int describeContents() {
        return 0;
    }

    // write your object's data to the passed-in Parcel
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
    }

    // this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };

    // example constructor that takes a Parcel and gives you an object populated with it's values
    private MyParcelable(Parcel in) {
        mData = in.readInt();
    }
}

Zauważ, że w przypadku, gdy masz więcej niż jedno pole do pobrania z danej paczki, musisz to zrobić w tej samej kolejności, w jakiej je umieściłeś (czyli w podejściu FIFO).

Gdy masz swoje obiekty realizować Parcelableto tylko kwestia oddania ich do swoich zamiarów z putExtra () :

Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);

Następnie możesz wyciągnąć je z powrotem za pomocą getParcelableExtra () :

Intent i = getIntent();
MyParcelable myParcelableObject = (MyParcelable) i.getParcelableExtra("name_of_extra");

Jeśli twoja klasa obiektów implementuje paczkowanie i szeregowalność, upewnij się, że wykonałeś rzut na jeden z poniższych:

i.putExtra("parcelable_extra", (Parcelable) myParcelableObject);
i.putExtra("serializable_extra", (Serializable) myParcelableObject);
Jeremy Logan
źródło
14
Jak można to zrealizować, gdy mData jest obiektem (np. JSONObject), a nie intem?
Peter Ajtai,
301
Dlaczego nie można po prostu przejść obok obiektu bez tego wszystkiego? Chcemy przekazać obiekt, który jest już w pamięci.
ceklock
110
@tecnotron, ponieważ jego aplikacje są w różnych procesach i mają osobne przestrzenie adresowe pamięci, nie można po prostu wysłać wskaźnika (odwołania) do bloku pamięci w procesie i oczekiwać, że będzie on dostępny w innym procesie.
marcinj
12
Co mam zrobić, jeśli nie mogę uczynić klasy obiektu możliwą do serializacji lub parceable?
Amel Jose
11
@ceklock powód tego jest następujący: Gdy aktywność jest opóźniona, a następnie zabita z pamięci, a następnie, gdy użytkownik otworzy ją z menu ostatnich, musi utworzyć Aktywność tam, gdzie została przerwana. Musi to być ten sam interfejs użytkownika. W tym przypadku obiekt nie znajduje się w pamięci. Ale intencją jest.
tasomaniac
194

Musisz serializować swój obiekt do pewnego rodzaju reprezentacji ciągu. Jedną z możliwych reprezentacji ciągów jest JSON, a jednym z najprostszych sposobów serializacji do / z JSON w Androidzie , jeśli mnie pytasz, jest Google GSON .

W takim przypadku po prostu wstawisz wartość zwracaną z ciągu (new Gson()).toJson(myObject);i pobierzesz wartość ciągu, a następnie użyjesz go, fromJsonaby z powrotem przekształcić go w obiekt.

Jeśli twój obiekt nie jest zbyt skomplikowany, może nie być warty narzutu i zamiast tego możesz rozważyć przekazanie oddzielnych wartości obiektu.

David Hedlund
źródło
19
Zgaduję, ponieważ odpowiedź fiXedd rozwiązuje ten sam problem bez korzystania z bibliotek zewnętrznych, w sposób, który jest po prostu tak bardzo preferowany, że nikt nigdy nie powinien mieć powodu, aby przejść przez zaproponowane przeze mnie rozwiązanie (nieświadome w tym czasie genialne rozwiązanie fiXedd)
David Hedlund,
5
Myślę, że to prawda. Ponadto JSON jest protokołem bardziej odpowiednim dla klienta / serwera, a nie między wątkami.
mobibob
16
Niekoniecznie zły pomysł, zwłaszcza. ponieważ Gson jest znacznie prostszy w użyciu niż implementacja paczkowania dla wszystkich obiektów, które chcesz wysłać.
uvesten
7
ponieważ używam gson w mojej aplikacji, jest to naprawdę łatwy i przyjemny sposób!
Lars,
16
String s = (new Gson().toJson(client));Cli client = new Gson().fromJson(s, Cli.class);
Dobra
155

Możesz wysłać obiekt możliwy do serializacji poprzez zamiar

// send where details is object
ClassName details = new ClassName();
Intent i = new Intent(context, EditActivity.class);
i.putExtra("Editing", details);
startActivity(i);


//receive
ClassName model = (ClassName) getIntent().getSerializableExtra("Editing");

And 

Class ClassName implements Serializable {
} 
Sridhar
źródło
2
możesz również wysyłać obiekty do paczki przez zamiar.
Tony Gil
6
„Serializowalny jest komicznie wolny na Androidzie. W wielu przypadkach granica jest bezużyteczna”. spójrz na stackoverflow.com/questions/5550670/…
Seraphim's
co jeśli działanie jest już uruchomione, czy należy wykonać 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
3
@ Wydajność Seraphima ma znaczenie, jeśli szeregujesz wiele obiektów, ale użytkownik nie zauważy, że szeregowanie jednego obiektu zajmuje 1 ms lub 10 ms. Jeśli celowy dodatek jest już, Serializableale nie Parcelablejest, rzadko warto się nim męczyć Parcelable.
Kevin Krumwiede
67

W sytuacjach, w których wiesz, że będziesz przekazywać dane w aplikacji, użyj „globałów” (takich jak klasy statyczne)

Oto, co Dianne Hackborn (hackbod - inżynier oprogramowania Google na Androida) powiedział w tej sprawie:

W sytuacjach, gdy wiesz, że działania przebiegają w tym samym procesie, możesz po prostu udostępniać dane za pośrednictwem globali. Na przykład możesz mieć globalny, HashMap<String, WeakReference<MyInterpreterState>> a kiedy tworzysz nowy MyInterpreterState, wymyślisz dla niego unikalną nazwę i umieścisz go na mapie hash; aby wysłać ten stan do innego działania, wystarczy umieścić unikatową nazwę na mapie skrótu, a po uruchomieniu drugiego działania może on pobrać MyInterpreterState z mapy skrótu o nazwie, którą otrzymuje.

Peter Ajtai
źródło
25
tak, wydawało mi się dziwne, że dostaliśmy te zamiary do wykorzystania, a następnie najlepszy inżynier mówi nam, abyśmy po prostu używali globałów do naszych danych. Ale tam jest prosto z ust koni.
Richard Le Mesurier
1
Czy słabe referencje nie byłyby tutaj ofiarą wywozu śmieci?
uLYsseus
1
@ uLYsseus sądzi, że taki jest pomysł, kiedy skończysz z nimi w działaniach ... więc gdy odpowiednie działania zostaną zniszczone, pozwoli to gc
Peter Ajtai
1
@RichardLeMesurier Myślałem o tym samym, ale potem spojrzałem na wyżej wspomniany post Grup dyskusyjnych Google od Dianne Hackborn, a ona wspomina, że ​​naprawdę jedynym problemem z globalsami byłby przy użyciu ukrytych zamiarów (które mogą uruchomić działanie poza pakietem ). Ma to sens, jak wspomina Dianne, ponieważ te działania najprawdopodobniej nie miałyby wiedzy o typach niestandardowych, które im przekazujesz. Kiedy to przeczytałem, stało się dla mnie jasne, dlaczego globały mogą nie być tak złą drogą w tych okolicznościach, i pomyślałem, że podzielę się, na wypadek, gdyby inni też byli ciekawi
BMB
intencje zostały przerobione do tego stopnia, że ​​można je było przenieść na inny komputer. co oczywiście nie jest dobrym sposobem na zrobienie czegokolwiek, gdy faktycznie masz tylko jeden proces, w którym się mnożysz. powody, dla których nie jest to dobre: ​​użycie pamięci, użycie procesora, użycie baterii. ten ostatni szczególnie dokonywał wyborów projektowych z intencjami dość kłopotliwymi z perspektywy czasu. są ludzie, którzy twierdzą, że to dobry pomysł, zwykle dlatego, że „tak powiedział Google”.
Lassi Kinnunen
49

Twoja klasa powinna implementować Serializable lub Parcelable.

public class MY_CLASS implements Serializable

Po zakończeniu możesz wysłać obiekt na putExtra

intent.putExtra("KEY", MY_CLASS_instance);

startActivity(intent);

Aby uzyskać dodatki, musisz tylko zrobić

Intent intent = getIntent();
MY_CLASS class = (MY_CLASS) intent.getExtras().getSerializable("KEY");

Jeśli twoja klasa implementuje Paczkowanie, użyj następnego

MY_CLASS class = (MY_CLASS) intent.getExtras().getParcelable("KEY");

Mam nadzieję, że to pomoże: D

Pedro Romão
źródło
6
Twoja klasa musi zaimplementować Serializablejest niewłaściwa. Klasa może Parcelablena przykład zaimplementować .
Marc Plano-Lesay
Jakie są różnice między Paczkowanym a Serializable @Kernald? pod względem czasu przetwarzania jest to wolniejsze / nie jest to najlepsza praktyka czy coś takiego?
gumuruh
Chociaż Serializablejest standardowym interfejsem Java, Parcelablejest specyficzny dla Androida. Pod względem wydajności Parcelable jest bardziej wydajny: developerphil.com/parcelable-vs-serializable
Marc Plano-Lesay
35

Krótka odpowiedź na szybką potrzebę

1. Zaimplementuj swoją klasę do postaci szeregowej.

Jeśli masz jakieś wewnętrzne klasy, nie zapomnij o ich wdrożeniu w Serializable !!

public class SportsData implements  Serializable
public class Sport implements  Serializable

List<Sport> clickedObj;

2. Wprowadź swój obiekt w zamiar

 Intent intent = new Intent(SportsAct.this, SportSubAct.class);
            intent.putExtra("sport", clickedObj);
            startActivity(intent);

3. I odbierz swój przedmiot w drugiej klasie aktywności

Intent intent = getIntent();
    Sport cust = (Sport) intent.getSerializableExtra("sport");
Sam
źródło
zobacz ten link, stackoverflow.com/questions/2139134/…
RejoylinLokeshwaran
To samo możesz osiągnąć, implementując interfejs Parcelable. Interfejs paczkowany wymaga więcej czasu na wdrożenie niż Serializable ze względu na rozmiar kodu. Ale działa szybciej niż Serializable i zużywa mniej zasobów.
Kwnstantinos Nikoloutsos
27

jeśli twoja klasa obiektów implementuje Serializable, nie musisz nic więcej robić, możesz przekazać obiekt możliwy do serializacji.
tego używam.

Vlad
źródło
24

implementować serializowalne w twojej klasie

public class Place implements Serializable{
        private int id;
        private String name;

        public void setId(int id) {
           this.id = id;
        }
        public int getId() {
           return id;
        }
        public String getName() {
           return name;
        }

        public void setName(String name) {
           this.name = name;
        }
}

Następnie możesz przekazać ten obiekt w sposób zamierzony

     Intent intent = new Intent(this, SecondAct.class);
     intent.putExtra("PLACE", Place);
     startActivity(intent);

W drugim ćwiczeniu możesz uzyskać takie dane

     Place place= (Place) getIntent().getSerializableExtra("PLACE");

Ale gdy dane staną się duże, ta metoda będzie wolna.

Ishan Fernando
źródło
16

Istnieje kilka sposobów uzyskiwania dostępu do zmiennych lub obiektów w innych klasach lub działaniu.

A. Baza danych

B. wspólne preferencje.

C. Serializacja obiektów.

D. Klasa, która może przechowywać wspólne dane, może zostać nazwana jako Common Utilities, zależna od Ciebie.

E. Przekazywanie danych przez intencje i interfejs paczkowany.

To zależy od potrzeb twojego projektu.

A. Baza danych

SQLite to baza danych Open Source, która jest wbudowana w system Android. SQLite obsługuje standardowe funkcje relacyjnej bazy danych, takie jak składnia SQL, transakcje i przygotowane wyciągi.

Samouczki - http://www.vogella.com/articles/AndroidSQLite/article.html

B. Wspólne preferencje

Załóżmy, że chcesz zapisać nazwę użytkownika. Tak więc będą teraz dwie rzeczy: kluczowa nazwa użytkownika, wartość wartości.

Jak przechowywać

 // Create object of SharedPreferences.
 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
 //now get Editor
 SharedPreferences.Editor editor = sharedPref.edit();
 //put your value
 editor.putString("userName", "stackoverlow");

 //commits your edits
 editor.commit();

Używając putString (), putBoolean (), putInt (), putFloat (), putLong () możesz zapisać żądany typ danych.

Jak pobrać

SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");

http://developer.android.com/reference/android/content/SharedPreferences.html

C. Serializacja obiektu

Serlizacja obiektów jest stosowana, jeśli chcemy zapisać stan obiektu, aby wysłać go przez sieć lub można go również użyć do własnych celów.

Używaj fasoli java i przechowuj w niej jako jedno z jego pól i używaj do tego getters i setter

JavaBeans to klasy Java, które mają właściwości. Traktuj właściwości jako zmienne instancji prywatnej. Ponieważ są prywatne, jedynym sposobem, aby uzyskać do nich dostęp spoza ich klasy, są metody w klasie. Metody zmieniające wartość właściwości nazywane są metodami ustawiającymi, a metody pobierające wartość właściwości nazywane są metodami pobierającymi.

public class VariableStorage implements Serializable  {

    private String inString ;

    public String getInString() {
        return inString;
    }

    public void setInString(String inString) {
        this.inString = inString;
    }


}

Ustaw zmienną w swojej metodzie pocztowej za pomocą

VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);

Następnie użyj obiektu Serialzation, aby serializować ten obiekt, a w drugiej klasie deserializować ten obiekt.

W serializacji obiekt może być reprezentowany jako ciąg bajtów, który zawiera dane obiektu, a także informacje o typie obiektu i typach danych przechowywanych w obiekcie.

Po zapisaniu serializowanego obiektu w pliku można go odczytać z pliku i dokonać deserializacji, to znaczy informacje o typie i bajty reprezentujące obiekt oraz jego dane można wykorzystać do odtworzenia obiektu w pamięci.

Jeśli chcesz samouczek do tego, skorzystaj z tego linku

http://javawithswaranga.blogspot.in/2011/08/serialization-in-java.html

Uzyskaj zmienną w innych klasach

D. Wspólne narzędzia

Możesz samodzielnie stworzyć klasę, która może zawierać wspólne dane, których często potrzebujesz w swoim projekcie.

Próba

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Przekazywanie danych przez zamiary

Zapoznaj się z tym samouczkiem, aby zapoznać się z tą opcją przekazywania danych.

http://shri.blog.kraya.co.uk/2010/04/26/android-parcel-data-to-pass-between-activities-using-parcelable-classes/

Nikhil Agrawal
źródło
Dobry samouczek, o którym wspomniałeś w (E) na temat przekazywania danych przez Intencje.
remick
16

Aby to zrobić, możesz użyć Android BUNDLE.

Utwórz pakiet ze swojej klasy, taki jak:

public Bundle toBundle() {
    Bundle b = new Bundle();
    b.putString("SomeKey", "SomeValue");

    return b;
}

Następnie przekaż ten pakiet za pomocą INTENT. Teraz możesz odtworzyć obiekt klasy, przekazując podobny pakiet

public CustomClass(Context _context, Bundle b) {
    context = _context;
    classMember = b.getString("SomeKey");
}

Zadeklaruj to w swojej klasie niestandardowej i użyj.

om252345
źródło
1
Preferowane do bezpośredniej realizacji paczkowej, IMHO. Pakiet sam w sobie implementuje opcję paczkowania, dzięki czemu zyskujesz na wydajności, unikając przy tym wszystkich problemów z jej implementacją. Zamiast tego możesz użyć par klucz-wartość do przechowywania i pobierania danych, które są znacznie bardziej niezawodne niż poleganie na zwykłej kolejności.
Risadinha
Paczkowanie wydaje mi się skomplikowane, w powyższej odpowiedzi używam metody toBundle z klasy na jego obiekcie, więc obiekt jest konwertowany na pakiet, a następnie możemy użyć konstruktora do konwersji pakietu na obiekt klasy.
om252345
To rozwiązanie jest wykonalne tylko wtedy, gdy przekazujesz pojedynczy obiekt przez zamiar.
TheIT
Jak json, ale myślę, że json jest lekki.
David
Czy obiekt, gdy go odzyskam, będzie tym samym obiektem lub kopią?
Markus
15

Dzięki za przesyłkę, ale znalazłem jeszcze jedno opcjonalne rozwiązanie

 public class getsetclass implements Serializable {
        private int dt = 10;
    //pass any object, drwabale 
        public int getDt() {
            return dt;
        }

        public void setDt(int dt) {
            this.dt = dt;
        }
    }

W ćwiczeniu pierwszym

getsetclass d = new getsetclass ();
                d.setDt(50);
                LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
                obj.put("hashmapkey", d);
            Intent inew = new Intent(SgParceLableSampelActivity.this,
                    ActivityNext.class);
            Bundle b = new Bundle();
            b.putSerializable("bundleobj", obj);
            inew.putExtras(b);
            startActivity(inew);

Uzyskaj dane w działaniu 2

 try {  setContentView(R.layout.main);
            Bundle bn = new Bundle();
            bn = getIntent().getExtras();
            HashMap<String, Object> getobj = new HashMap<String, Object>();
            getobj = (HashMap<String, Object>) bn.getSerializable("bundleobj");
            getsetclass  d = (getsetclass) getobj.get("hashmapkey");
        } catch (Exception e) {
            Log.e("Err", e.getMessage());
        }
1140237
źródło
1
dobra odpowiedź, ale podnieś swoje standardy kodowania ... +1 za wprowadzenie Serializowalnego w konkursie, jednak paczki są znacznie szybsze ...
Amit
13

Używam Gsona z jego tak potężnym i prostym interfejsem API, aby przesyłać obiekty między czynnościami,

Przykład

// This is the object to be sent, can be any object
public class AndroidPacket {

    public String CustomerName;

   //constructor
   public AndroidPacket(String cName){
       CustomerName = cName;
   }   
   // other fields ....


    // You can add those functions as LiveTemplate !
    public String toJson() {
        Gson gson = new Gson();
        return gson.toJson(this);
    }

    public static AndroidPacket fromJson(String json) {
        Gson gson = new Gson();
        return gson.fromJson(json, AndroidPacket.class);
    }
}

2 funkcje dodajesz je do obiektów, które chcesz wysłać

Stosowanie

Wyślij obiekt od A do B.

    // Convert the object to string using Gson
    AndroidPacket androidPacket = new AndroidPacket("Ahmad");
    String objAsJson = androidPacket.toJson();

    Intent intent = new Intent(A.this, B.class);
    intent.putExtra("my_obj", objAsJson);
    startActivity(intent);

Odbierz w B

@Override
protected void onCreate(Bundle savedInstanceState) {        
    Bundle bundle = getIntent().getExtras();
    String objAsJson = bundle.getString("my_obj");
    AndroidPacket androidPacket = AndroidPacket.fromJson(objAsJson);

    // Here you can use your Object
    Log.d("Gson", androidPacket.CustomerName);
}

Używam go prawie w każdym projekcie i nie mam problemów z wydajnością.

MBH
źródło
Dzięki, dzięki temu zaoszczędziłem godziny nadmiernej komplikacji.
Hristo Stoyanov
10

Walczyłem z tym samym problemem. Rozwiązałem to za pomocą klasy statycznej, przechowując dowolne dane w HashMap. Ponadto korzystam z rozszerzenia standardowej klasy Activity, w której zastąpiłem metody onCreate onDestroy, aby ukryć transport danych i ich czyszczenie. Niektóre śmieszne ustawienia muszą zostać zmienione, np. Obsługa orientacji.

Adnotacja: Niedostarczenie ogólnych obiektów, które mają być przekazane do innej czynności, to ból w dupę. To tak, jakby strzelić sobie w kolano i mieć nadzieję na wygranie 100 metrów. „Parcable” nie jest wystarczającym substytutem. Rozśmiesza mnie ... Nie chcę implementować tego interfejsu do mojego wolnego od technologii API, ponieważ mniej chcę wprowadzić nową warstwę ... Jak to możliwe, że jesteśmy w programowaniu mobilnym tak daleko od nowoczesny paradygmat ...

oopexpert
źródło
9

W pierwszej aktywności:

intent.putExtra("myTag", yourObject);

A w drugim:

myCustomObject myObject = (myCustomObject) getIntent().getSerializableExtra("myTag");

Nie zapomnij ustawić niestandardowego obiektu na Serializable:

public class myCustomObject implements Serializable {
...
}
Rudi
źródło
Paczka jest lepsza niż Serializable! Unikaj używania Serializable w kodzie Androida!
Filipe Brito,
7

Innym sposobem na to jest użycie Applicationobiektu (android.app.Application). Zdefiniujesz to w swoim AndroidManifest.xmlpliku jako:

<application
    android:name=".MyApplication"
    ...

Następnie możesz wywołać to z dowolnej aktywności i zapisać obiekt w Applicationklasie.

W FirstActivity:

MyObject myObject = new MyObject();
MyApplication app = (MyApplication) getApplication();
app.setMyObject(myObject);

W SecondActivity wykonaj:

MyApplication app = (MyApplication) getApplication();
MyObject retrievedObject = app.getMyObject(myObject);

Jest to przydatne, jeśli masz obiekty o zasięgu na poziomie aplikacji, tzn. Muszą być używane w całej aplikacji. TheParcelable metoda jest jeszcze lepsza, jeśli chcesz jawnie kontrolować zakres obiektu lub jeśli zakres jest ograniczony.

Pozwala to jednak uniknąć Intentscałkowitego użycia . Nie wiem czy ci odpowiadają. Innym sposobem, w jaki to wykorzystałem, jest intwysyłanie identyfikatorów obiektów poprzez zamiary i pobieranie obiektów, które mam w Mapach w Applicationobiekcie.

Saad Farooq
źródło
1
To nie jest właściwy sposób na robienie rzeczy, ponieważ obiekty mogą być zmienne, twój może działać, jeśli mówisz o obiekcie statycznym podczas cyklu życia aplikacji, ale czasami potrzebujemy pasywnych obiektów, które mogą być generowane za pomocą usługi internetowej, a więc stackoverflow.com / a / 2736612/716865
Muhannad A.Alhariri
Użyłem go z powodzeniem z obiektami generowanymi z usług sieciowych, mając zakres aplikacji, w Mapktórym obiekty są przechowywane i pobierane za pomocą identyfikatora. Jedynym prawdziwym problemem związanym z tym podejściem jest to, że Android po pewnym czasie usuwa pamięć, więc musisz sprawdzić wartości zerowe w swoim polu OnResume (myślę, że obiekty przekazane w zamierzeniu są utrwalane, ale nie jestem pewien). Poza tym nie uważam tego za znacznie gorszy.
Saad Farooq
To najlepsza odpowiedź. Pokazuje, w jaki sposób różne działania mogą odnosić się do tego samego modelu danych. Długo zajęło mi odkrycie tego!
Markus
6

w swoim modelu klasy (Object) zaimplementuj Serializable, na przykład:

public class MensajesProveedor implements Serializable {

    private int idProveedor;


    public MensajesProveedor() {
    }

    public int getIdProveedor() {
        return idProveedor;
    }

    public void setIdProveedor(int idProveedor) {
        this.idProveedor = idProveedor;
    }


}

i twoja pierwsza aktywność

MensajeProveedor mp = new MensajeProveedor();
Intent i = new Intent(getApplicationContext(), NewActivity.class);
                i.putExtra("mensajes",mp);
                startActivity(i);

i twoja druga aktywność (NewActivity)

        MensajesProveedor  mensajes = (MensajesProveedor)getIntent().getExtras().getSerializable("mensajes");

powodzenia!!

David Hackro
źródło
6
public class SharedBooking implements Parcelable{

    public int account_id;
    public Double betrag;
    public Double betrag_effected;
    public int taxType;
    public int tax;
    public String postingText;

    public SharedBooking() {
        account_id = 0;
        betrag = 0.0;
        betrag_effected = 0.0;
        taxType = 0;
        tax = 0;
        postingText = "";
    }

    public SharedBooking(Parcel in) {
        account_id = in.readInt();
        betrag = in.readDouble();
        betrag_effected = in.readDouble();
        taxType = in.readInt();
        tax = in.readInt();
        postingText = in.readString();
    }

    public int getAccount_id() {
        return account_id;
    }
    public void setAccount_id(int account_id) {
        this.account_id = account_id;
    }
    public Double getBetrag() {
        return betrag;
    }
    public void setBetrag(Double betrag) {
        this.betrag = betrag;
    }
    public Double getBetrag_effected() {
        return betrag_effected;
    }
    public void setBetrag_effected(Double betrag_effected) {
        this.betrag_effected = betrag_effected;
    }
    public int getTaxType() {
        return taxType;
    }
    public void setTaxType(int taxType) {
        this.taxType = taxType;
    }
    public int getTax() {
        return tax;
    }
    public void setTax(int tax) {
        this.tax = tax;
    }
    public String getPostingText() {
        return postingText;
    }
    public void setPostingText(String postingText) {
        this.postingText = postingText;
    }
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(account_id);
        dest.writeDouble(betrag);
        dest.writeDouble(betrag_effected);
        dest.writeInt(taxType);
        dest.writeInt(tax);
        dest.writeString(postingText);

    }

    public static final Parcelable.Creator<SharedBooking> CREATOR = new Parcelable.Creator<SharedBooking>()
    {
        public SharedBooking createFromParcel(Parcel in)
        {
            return new SharedBooking(in);
        }
        public SharedBooking[] newArray(int size)
        {
            return new SharedBooking[size];
        }
    };

}

Przekazywanie danych:

Intent intent = new Intent(getApplicationContext(),YourActivity.class);
Bundle bundle = new Bundle();
i.putParcelableArrayListExtra("data", (ArrayList<? extends Parcelable>) dataList);
intent.putExtras(bundle);
startActivity(intent);

Odzyskiwanie danych:

Bundle bundle = getIntent().getExtras();
dataList2 = getIntent().getExtras().getParcelableArrayList("data");
Adnan Abdollah Zaki
źródło
5

najłatwiejszym rozwiązaniem, jakie znalazłem, jest ... utworzenie klasy ze statycznymi elementami danych z ustawiaczami getterów.

ustawić z jednego działania i uzyskać z innego działania tego obiektu.

aktywność A

mytestclass.staticfunctionSet("","",""..etc.);

aktywność b

mytestclass obj= mytestclass.staticfunctionGet();
UMAR
źródło
1
lub klasa serializowalna creata, aby przejść do innego działania, cokolwiek chcesz przekazać.
UMAR
9
Pamiętaj tylko, aby nie kłaść dużych, grubych przedmiotów. Żywotność tego obiektu będzie taka sama jak żywotność aplikacji. I nigdy nie przechowuj wyświetleń. Ta metoda gwarantuje także wycieki pamięci.
Reno,
1
Ta odpowiedź jest przydatna, ale nie lepszym rozwiązaniem pod względem optymalizacji pamięci i zasobów
Atul Bhardwaj
1
To łamie zasady OOP, wprowadzając zmienne globalne. Nigdy nie wiadomo, w jakim są stanie, czy są ustawione, czy nie, są używane przez wiele wątków i trzeba poradzić sobie z tą złożonością. Zazwyczaj jest to dobry wyciek pamięci, ponieważ nawet nie wiadomo, kiedy uwolnić te zmienne. Nie mówiąc już, że wprowadza twarde bezpośrednie połączenie między różnymi modułami aplikacji.
afrish
2
WTF? Pozostałe dwie odpowiedzi są o wiele lepsze.
IcyFlame
4

możesz użyć metod putExtra (Serializable ..) i getSerializableExtra () do przekazywania i pobierania obiektów typu klasy; będziesz musiał oznaczyć klasę jako Serializowalną i upewnić się, że wszystkie zmienne członkowskie również są możliwe do serializacji ...

zero
źródło
4

Utwórz aplikację na Androida

Plik >> Nowy >> Aplikacja na Androida

Wprowadź nazwę projektu: android-pass-object-to-activity

Pakcage: com.hmkcode.android

Zachowaj inne błędne wybory, idź Dalej, aż dojdziesz do końca

Przed rozpoczęciem tworzenia aplikacji musimy utworzyć klasę POJO „Osoba”, której użyjemy do przesłania obiektu z jednej czynności do drugiej. Zauważ, że klasa implementuje interfejs Serializable.

Person.java

package com.hmkcode.android;
import java.io.Serializable;

public class Person implements Serializable{

    private static final long serialVersionUID = 1L;

    private String name;
    private int age;

        // getters & setters....

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }   
}

Dwa układy dla dwóch działań

Activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView
        android:id="@+id/tvName"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center_horizontal"
        android:text="Name" />

    <EditText
        android:id="@+id/etName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:ems="10" >
        <requestFocus />
    </EditText>
</LinearLayout>

<LinearLayout
     android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
<TextView
    android:id="@+id/tvAge"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
    android:text="Age" />
<EditText
    android:id="@+id/etAge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:ems="10" />
</LinearLayout>

<Button
    android:id="@+id/btnPassObject"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="Pass Object to Another Activity" />

</LinearLayout>

activity_another.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
 >

<TextView
    android:id="@+id/tvPerson"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:layout_gravity="center"
    android:gravity="center_horizontal"
 />

</LinearLayout>

Dwie klasy aktywności

1) ActivityMain.java

package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

Button btnPassObject;
EditText etName, etAge;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnPassObject = (Button) findViewById(R.id.btnPassObject);
    etName = (EditText) findViewById(R.id.etName);
    etAge = (EditText) findViewById(R.id.etAge);

    btnPassObject.setOnClickListener(this);
}

@Override
public void onClick(View view) {

    // 1. create an intent pass class name or intnet action name 
    Intent intent = new Intent("com.hmkcode.android.ANOTHER_ACTIVITY");

    // 2. create person object
    Person person = new Person();
    person.setName(etName.getText().toString());
    person.setAge(Integer.parseInt(etAge.getText().toString()));

    // 3. put person in intent data
    intent.putExtra("person", person);

    // 4. start the activity
    startActivity(intent);
}

}

2) AnotherActivity.java

package com.hmkcode.android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class AnotherActivity extends Activity {

TextView tvPerson;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_another);

    // 1. get passed intent 
    Intent intent = getIntent();

    // 2. get person object from intent
    Person person = (Person) intent.getSerializableExtra("person");

    // 3. get reference to person textView 
    tvPerson = (TextView) findViewById(R.id.tvPerson);

    // 4. display name & age on textView 
    tvPerson.setText(person.toString());

}
}
MFP
źródło
4

Korzystając z biblioteki Google Gson, możesz przekazać obiekt do innych działań. Właściwie przekonwertujemy obiekt w postaci ciągu json, a po przejściu do innej aktywności ponownie przekonwertujemy obiekt na taki jak ten

Rozważ taką klasę fasoli jak ta

 public class Example {
    private int id;
    private String name;

    public Example(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Musimy przekazać obiekt klasy Przykład

Example exampleObject=new Example(1,"hello");
String jsonString = new Gson().toJson(exampleObject);
Intent nextIntent=new Intent(this,NextActivity.class);
nextIntent.putExtra("example",jsonString );
startActivity(nextIntent);

Do odczytu musimy wykonać operację odwrotną w NextActivity

 Example defObject=new Example(-1,null);
    //default value to return when example is not available
    String defValue= new Gson().toJson(defObject);
    String jsonString=getIntent().getExtras().getString("example",defValue);
    //passed example object
    Example exampleObject=new Gson().fromJson(jsonString,Example .class);

Dodaj tę zależność w stopniach

compile 'com.google.code.gson:gson:2.6.2'
Jinesh Francis
źródło
3
Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);
startACtivity(i);
Manas Ranjan
źródło
3

Wiem, że jest późno, ale to bardzo proste. Wszystko, co musisz zrobić, to pozwolić swojej klasie zaimplementować Serializable jak

public class MyClass implements Serializable{

}

wtedy możesz przejść do takiego celu

Intent intent=......
MyClass obje=new MyClass();
intent.putExtra("someStringHere",obje);

Aby to zrobić, po prostu zadzwoń

MyClass objec=(MyClass)intent.getExtra("theString");
suulisin
źródło
2

Jeśli i tak masz klasę singleton (usługa fx), która działa jako brama do warstwy modelu, możesz ją rozwiązać, wprowadzając zmienną w tej klasie z pobierającymi i ustawiającymi.

W ćwiczeniu 1:

Intent intent = new Intent(getApplicationContext(), Activity2.class);
service.setSavedOrder(order);
startActivity(intent);

W ćwiczeniu 2:

private Service service;
private Order order;

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

    service = Service.getInstance();
    order = service.getSavedOrder();
    service.setSavedOrder(null) //If you don't want to save it for the entire session of the app.
}

Czynny:

private static Service instance;

private Service()
{
    //Constructor content
}

public static Service getInstance()
{
    if(instance == null)
    {
        instance = new Service();
    }
    return instance;
}
private Order savedOrder;

public Order getSavedOrder()
{
    return savedOrder;
}

public void setSavedOrder(Order order)
{
    this.savedOrder = order;
}

To rozwiązanie nie wymaga serializacji ani innego „pakowania” danego obiektu. Ale będzie to korzystne tylko wtedy, gdy korzystasz z tego rodzaju architektury.

Kitalda
źródło
Jakie są wady tego podejścia? Wydaje się tak logiczny i smukły. Zawsze czytam, że nie powinieneś tego robić, ale nigdy nie otrzymuję dobrego wyjaśnienia, co może pójść nie tak.
Markus
Ponieważ nie mogę już edytować mojego komentarza: czy nie jest to jedyne możliwe rozwiązanie, aby uzyskać odwołanie do obiektu zamiast kopii? Muszę pobrać ten sam obiekt, a nie kopię!
Markus
Myślę, że jest to nieco odradzane z powodu wysokiego sprzężenia, do którego prowadzi. Ale tak, o ile widzę, takie podejście jest najbardziej realne, jeśli potrzebujesz rzeczywistego obiektu. Jak zawsze w programowaniu, możesz robić, co chcesz, po prostu chcesz to robić ostrożnie. To rozwiązanie działało dla mnie i wolę je, ponieważ i tak używam tej architektury.
Kitalda
W rzeczywistości rozszerzyłem klasę aplikacji i tam zapisałem swój model danych. W Intentach przekazałem tylko identyfikator obiektów danych, których można użyć do pobrania oryginalnego obiektu z klasy Application. Rozszerzona klasa aplikacji powiadamia również wszystkie obiekty korzystające z modelu danych, jeśli zmienia się ono za pomocą standardowej koncepcji detektora. Wiem, że pasuje to tylko do mojego przypadku, w którym muszę współużytkować model danych w całej aplikacji, ale w tym przypadku jest on doskonały i nie wymaga też klas statycznych i pól!
Markus
2

Zdecydowanie najłatwiejszy sposób na paczkowanie obiektów IMHO. Wystarczy dodać znacznik adnotacji nad obiektem, który ma być paczkowany.

Przykład z biblioteki znajduje się poniżej https://github.com/johncarl81/parceler

@Parcel
public class Example {
    String name;
    int age;

    public Example(){ /*Required empty bean constructor*/ }

    public Example(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String getName() { return name; }

    public int getAge() { return age; }
}
Ryan
źródło
2

Najpierw zaimplementuj Paczkę w swojej klasie. Następnie przekaż obiekt w ten sposób.

SendActivity.java

ObjectA obj = new ObjectA();

// Set values etc.

Intent i = new Intent(this, MyActivity.class);
i.putExtra("com.package.ObjectA", obj);

startActivity(i);

ReceiveActivity.java

Bundle b = getIntent().getExtras();
ObjectA obj = b.getParcelable("com.package.ObjectA");

Ciąg pakietu nie jest konieczny, po prostu ciąg musi być taki sam w obu działaniach

ODNIESIENIE

Arpit Patel
źródło
2

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

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "[email protected]");
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);
1101821
źródło
2

W Koltinie

Dodaj rozszerzenie kotlin do swojego build.gradle.

apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
   }
}

Następnie utwórz swoją klasę danych w ten sposób.

@Parcelize
data class Sample(val id: Int, val name: String) : Parcelable

Przekaż obiekt z zamiarem

val sample = Sample(1,"naveen")

val intent = Intent(context, YourActivity::class.java)
    intent.putExtra("id", sample)
    startActivity(intent)

Zdobądź obiekt z zamiarem

val sample = intent.getParcelableExtra("id")
Naveen
źródło
Czy to wciąż eksperymentalne?
ShadeToD
2

Najłatwiejszym i java sposobem jest: implementować serializable w twojej klasie pojo / model

Zalecane dla Androida dla widoku wydajności: uczyń model paczkowym

Ashok Kumar
źródło
1

Najprościej byłoby po prostu użyć następującego, gdy element jest łańcuchem:

intent.putextra("selected_item",item)

Do odbioru:

String name = data.getStringExtra("selected_item");
ankish
źródło
3
tylko dla ciągu, liczb całkowitych itp., ale chcę obiekt i używanie obiektu statycznego jest jego jedyne możliwe.
UMAR