Wie sende ich ein Objekt mithilfe von Absichten von einer Android-Aktivität zu einer anderen?

849

Wie kann ich ein Objekt eines benutzerdefinierten Typs mithilfe der Methode der Klasse Intent von einer Aktivität an eine andere übergeben ?putExtra()

UMAR
quelle
@UMMA - Sie müssen Ihre Fragen nicht ständig als "Community Wiki" markieren. Schauen Sie hier: meta.stackexchange.com/questions/11740/…
Dave Webb
1
@Paresh: Der von Ihnen angegebene Link ist defekt. Könnten Sie bitte eine Alternative anbieten?
Antiplex
Schauen Sie sich diese Antwort an. stackoverflow.com/questions/8857546/…
Heitor Colangelo
Ich fand eine einfache und elegante Methode stackoverflow.com/a/37774966/6456129
Yessy

Antworten:

751

Wenn Sie nur Objekte herumreichen, wurde Parcelable dafür entwickelt. Es erfordert ein wenig mehr Aufwand , um den Einsatz als Java native Serialisierung verwenden, aber es ist viel schneller (und ich meine Art und Weise, WAY schneller).

Ein einfaches Beispiel für die Implementierung aus den Dokumenten ist:

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

Beachten Sie, dass Sie in dem Fall, in dem Sie mehr als ein Feld von einem bestimmten Paket abrufen müssen, dies in derselben Reihenfolge tun müssen, in der Sie es eingegeben haben (dh bei einem FIFO-Ansatz).

Sobald Sie Ihre Objekte implementieren Parcelablees ist nur eine Frage von ihnen in Putten Intents mit putExtra () :

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

Dann können Sie sie mit getParcelableExtra () wieder herausziehen :

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

Wenn Ihre Objektklasse Parcelable und Serializable implementiert, stellen Sie sicher, dass Sie eine der folgenden Optionen verwenden:

i.putExtra("parcelable_extra", (Parcelable) myParcelableObject);
i.putExtra("serializable_extra", (Serializable) myParcelableObject);
Jeremy Logan
quelle
14
Wie würde dies implementiert, wenn mData ein Objekt (z. B. JSONObject) und kein int ist?
Peter Ajtai
301
Warum kann man das Objekt nicht einfach ohne all das passieren? Wir wollen ein Objekt übergeben, das sich bereits im Speicher befindet.
ceklock
110
@tecnotron seine Beacuse-Apps befinden sich in verschiedenen Prozessen und haben separate Speicheradressräume. Sie können nicht einfach einen Zeiger (eine Referenz) auf den Speicherblock in Ihrem Prozess senden und erwarten, dass dieser in einem anderen Prozess verfügbar ist.
März
12
Was mache ich, wenn ich die Klasse des Objekts nicht serialisierbar oder parceable machen kann?
Amel Jose
11
@ceklock Der Grund dafür ist folgender: Wenn die Aktivität zurückbleibt und später aus dem Speicher beendet wird und der Benutzer sie dann über das Menü "Letzte" öffnet, muss er die Aktivität dort erstellen, wo sie aufgehört hat. Es muss dieselbe Benutzeroberfläche sein. Das Objekt befindet sich in diesem Fall nicht im Speicher. Aber die Absicht ist.
Tasomaniac
194

Sie müssen Ihr Objekt in eine Art Zeichenfolgendarstellung serialisieren. Eine mögliche Zeichenfolgendarstellung ist JSON, und eine der einfachsten Möglichkeiten, um von / nach JSON in Android zu serialisieren, ist, wenn Sie mich fragen, Google GSON .

In diesem Fall geben Sie einfach den Zeichenfolgenrückgabewert von ein, (new Gson()).toJson(myObject);rufen den Zeichenfolgenwert ab und verwenden ihn fromJson, um ihn wieder in Ihr Objekt umzuwandeln.

Wenn Ihr Objekt jedoch nicht sehr komplex ist, ist es möglicherweise den Aufwand nicht wert, und Sie können stattdessen die separaten Werte des Objekts übergeben.

David Hedlund
quelle
19
Ich vermute, weil die Antwort von fiXedd das gleiche Problem ohne die Verwendung externer Bibliotheken auf eine Weise löst, die einfach so vorzuziehen ist, dass niemand jemals einen Grund haben sollte, sich für die von mir bereitgestellte Lösung zu entscheiden (ohne es zu wissen) fiXedds brillante Lösung)
David Hedlund
5
Ich denke das ist richtig. Darüber hinaus ist JSON ein Protokoll, das eher für Client / Server und nicht für Thread-to-Thread geeignet ist.
Mobibob
16
Nicht unbedingt eine schlechte Idee, insb. da Gson viel einfacher zu verwenden ist, als Parcelable für alle Objekte zu implementieren, die Sie senden möchten.
Uvesten
7
Da ich Gson in meiner App verwende, ist dies ein sehr einfacher und netter Weg!
Lars
16
Schöne Antwort, obwohl vollständige Lösung wäre String s = (new Gson().toJson(client));und dannCli client = new Gson().fromJson(s, Cli.class);
Joaquin Iurchuk
155

Sie können serialisierbare Objekte absichtlich senden

// 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
quelle
2
Sie können Paketobjekte auch absichtlich senden.
Tony Gil
6
"Serializable ist auf Android komisch langsam. Borderline ist in vielen Fällen sogar nutzlos." Schauen Sie sich stackoverflow.com/questions/5550670/… an
Seraphims
Was ist, wenn die Aktivität bereits ausgeführt wird? Muss startActivity (i) ausgeführt werden? ? Ich meine, kann ich Aktivität A dazu bringen , Aktivität B aufzurufen , und das gibt Daten an Aktivität A zurück ? bin ich verwirrt
Francisco Corrales Morales
3
Die Leistung von @ Seraphim ist wichtig, wenn Sie viele Objekte serialisieren. Der Benutzer merkt jedoch nicht, ob die Serialisierung eines Objekts 1 ms oder 10 ms dauert. Wenn ein Vorsatz-Extra bereits vorhanden ist, Serializableaber nicht Parcelable, lohnt es sich selten, es zu machen Parcelable.
Kevin Krumwiede
67

Verwenden Sie in Situationen, in denen Sie wissen, dass Sie Daten innerhalb einer Anwendung übergeben, "Globals" (wie statische Klassen).

Hier ist, was Dianne Hackborn (hackbod - ein Google Android Software Engineer) zu diesem Thema zu sagen hatte:

In Situationen, in denen Sie wissen, dass die Aktivitäten im selben Prozess ausgeführt werden, können Sie Daten einfach über globale Elemente freigeben. Sie könnten beispielsweise einen globalen Namen haben HashMap<String, WeakReference<MyInterpreterState>> und beim Erstellen eines neuen MyInterpreterState einen eindeutigen Namen dafür erstellen und in die Hash-Map einfügen. Um diesen Status an eine andere Aktivität zu senden, geben Sie einfach den eindeutigen Namen in die Hash-Map ein. Wenn die zweite Aktivität gestartet wird, kann der MyInterpreterState mit dem Namen, den er empfängt, aus der Hash-Map abgerufen werden.

Peter Ajtai
quelle
25
Ja, ich fand es seltsam, dass wir diese Absichten erhalten, und dann sagt uns ein Top-Ingenieur, wir sollen nur Globale für unsere Daten verwenden. Aber da ist es direkt aus dem Maul des Pferdes.
Richard Le Mesurier
1
Wäre eine schwache Auffrischung hier nicht ein Opfer der Müllabfuhr?
ULYsseus
1
@uLYsseus denke, das ist die Idee, wenn Sie mit ihnen in den Aktivitäten fertig sind ... Wenn die relevanten Aktivitäten zerstört sind, wird es gc ermöglichen
Peter Ajtai
1
@RichardLeMesurier Ich habe das Gleiche gedacht, aber dann habe ich mir den oben genannten Beitrag von Google Groups von Dianne Hackborn angesehen und sie erwähnt, dass das einzige Problem mit Globals die Verwendung impliziter Absichten ist (die eine Aktivität außerhalb Ihres Pakets starten können ). Dies ist sinnvoll, wie Dianne erwähnt, da diese Aktivitäten höchstwahrscheinlich keine Kenntnis von den benutzerdefinierten Typen haben, die Sie an sie übergeben. Nachdem ich das gelesen hatte, wurde mir klarer, warum Globals unter den gegebenen Umständen keine so schlechte Route sein könnten, und ich dachte, ich würde sie teilen, falls andere auch neugierig wären
BMB
Die Absichten wurden bis zu einem Punkt überarbeitet, an dem die Absichten an einen anderen Computer weitergegeben werden konnten. Dies ist offensichtlich kein guter Weg, um etwas zu tun, wenn Sie tatsächlich nur einen Prozess haben, an dem Sie herumspielen. Gründe, warum es nicht gut ist: Speichernutzung, CPU-Nutzung, Batterieverbrauch. Der letzte traf besonders die Designentscheidungen mit Absichten, die im Nachhinein ziemlich verwirrend waren. Es gibt Leute, die darauf bestehen, dass sie eine gute Idee sind, normalerweise, weil "Google das gesagt hat".
Lassi Kinnunen
49

Ihre Klasse sollte Serializable oder Parcelable implementieren.

public class MY_CLASS implements Serializable

Sobald Sie fertig sind, können Sie ein Objekt auf putExtra senden

intent.putExtra("KEY", MY_CLASS_instance);

startActivity(intent);

Um Extras zu bekommen, müssen Sie nur noch tun

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

Wenn Ihre Klasse Parcelable implementiert, verwenden Sie next

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

Ich hoffe es hilft: D.

Pedro Romão
quelle
6
Ihre Klasse muss implementieren Serializableist falsch. Die Klasse kann Parcelablezum Beispiel implementieren .
Marc Plano-Lesay
Was ist der Unterschied zwischen Parcelable und Serializable @Kernald? In Bezug auf die Verarbeitungszeit ist es langsamer / nicht Best Practice oder so?
Gumuruh
Während Serializablees sich um eine Standard-Java-Oberfläche handelt, Parcelableist es Android-spezifisch. In Bezug auf die Leistung ist Parcelable effizienter: developerphil.com/parcelable-vs-serializable
Marc Plano-Lesay
35

Kurze Antwort für schnelle Bedürfnisse

1. Implementieren Sie Ihre Klasse in Serializable.

Wenn Sie innere Klassen haben, vergessen Sie nicht, diese auch in Serializable zu implementieren !!

public class SportsData implements  Serializable
public class Sport implements  Serializable

List<Sport> clickedObj;

2. Setzen Sie Ihr Objekt in Absicht

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

3. Und erhalten Sie Ihr Objekt in der anderen Aktivitätsklasse

Intent intent = getIntent();
    Sport cust = (Sport) intent.getSerializableExtra("sport");
Sam
quelle
siehe diesen Link, stackoverflow.com/questions/2139134/…
RejoylinLokeshwaran
Sie können dasselbe erreichen, indem Sie die Parcelable-Schnittstelle implementieren. Die Implementierung der Paketschnittstelle dauert im Vergleich zu Serializable aufgrund der Codegröße länger. Es ist jedoch schneller als serialisierbar und verbraucht weniger Ressourcen.
Kwnstantinos Nikoloutsos
27

Wenn Ihre Objektklasse implementiert ist Serializable, müssen Sie nichts weiter tun. Sie können ein serialisierbares Objekt übergeben.
das ist was ich benutze.

Vlad
quelle
24

Implementieren Sie serialisierbar in Ihrer Klasse

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

Dann können Sie dieses Objekt absichtlich übergeben

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

In der zweiten Aktivität können Sie solche Daten erhalten

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

Wenn die Daten jedoch groß werden, ist diese Methode langsam.

Ishan Fernando
quelle
16

Sie können Android BUNDLE verwenden, um dies zu tun.

Erstellen Sie ein Bundle aus Ihrer Klasse wie folgt:

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

    return b;
}

Dann übergeben Sie dieses Bundle mit INTENT. Jetzt können Sie Ihr Klassenobjekt neu erstellen, indem Sie ein Bundle wie übergeben

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

Deklarieren Sie dies in Ihrer benutzerdefinierten Klasse und verwenden Sie es.

om252345
quelle
1
IMHO der direkten Implementierung von Parcelable vorzuziehen. Bundle implementiert Parcelable selbst, sodass Sie immer noch den Leistungsgewinn erzielen und gleichzeitig die Probleme vermeiden, es selbst zu implementieren. Stattdessen können Sie Schlüssel-Wert-Paare verwenden, um Daten zu speichern und abzurufen, die bei weitem robuster sind, als wenn Sie sich nur auf die Reihenfolge verlassen.
Risadinha
Parcelable scheint mir kompliziert zu sein. In meiner obigen Antwort verwende ich die toBundle-Methode aus der Klasse für das Objekt, sodass das Objekt in ein Bundle konvertiert wird. Anschließend können wir den Konstruktor verwenden, um das Bundle in ein Klassenobjekt zu konvertieren.
Om252345
Diese Lösung ist nur möglich, wenn Sie ein einzelnes Objekt durch eine Absicht führen.
TheIT
Wie Json, aber Json ist leicht, denke ich.
David
Wird das Objekt beim Abrufen dasselbe Objekt oder eine Kopie sein?
Markus
16

Es gibt verschiedene Möglichkeiten, auf Variablen oder Objekte in anderen Klassen oder Aktivitäten zuzugreifen.

Eine Datenbank

B. gemeinsame Einstellungen.

C. Objektserialisierung.

D. Eine Klasse, die allgemeine Daten enthalten kann, kann als Common Utilities bezeichnet werden, abhängig von Ihnen.

E. Weitergabe von Daten über Absichten und Paketschnittstelle.

Dies hängt von Ihren Projektanforderungen ab.

A. Datenbank

SQLite ist eine Open Source-Datenbank, die in Android eingebettet ist. SQLite unterstützt standardmäßige relationale Datenbankfunktionen wie SQL-Syntax, Transaktionen und vorbereitete Anweisungen.

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

B. Gemeinsame Einstellungen

Angenommen, Sie möchten den Benutzernamen speichern. Es gibt also jetzt zwei Dinge: einen Schlüsselbenutzernamen , Wert Wert.

Wie zu speichern

 // Create an 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();

Mit putString (), putBoolean (), putInt (), putFloat (), putLong () können Sie Ihren gewünschten Datentyp speichern.

Wie zu holen

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

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

C. Objektserialisierung

Die Objektserialisierung wird verwendet, wenn ein Objektstatus gespeichert werden soll, um ihn über das Netzwerk zu senden, oder wenn Sie ihn auch für Ihren Zweck verwenden können.

Verwenden Sie Java-Bohnen und speichern Sie sie als eines seiner Felder. Verwenden Sie dafür Getter und Setter

JavaBeans sind Java-Klassen mit Eigenschaften. Stellen Sie sich Eigenschaften als private Instanzvariablen vor. Da sie privat sind, können sie nur über Methoden in der Klasse von außerhalb ihrer Klasse aufgerufen werden. Die Methoden, die den Wert einer Eigenschaft ändern, werden als Setter-Methoden bezeichnet, und die Methoden, die den Wert einer Eigenschaft abrufen, werden als Getter-Methoden bezeichnet.

public class VariableStorage implements Serializable  {

    private String inString ;

    public String getInString() {
        return inString;
    }

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


}

Stellen Sie die Variable in Ihrer Mail-Methode mit ein

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

Verwenden Sie dann das Objekt Serialzation, um dieses Objekt zu serialisieren, und deserialisieren Sie dieses Objekt in Ihrer anderen Klasse.

Bei der Serialisierung kann ein Objekt als eine Folge von Bytes dargestellt werden, die die Daten des Objekts sowie Informationen über den Objekttyp und die im Objekt gespeicherten Datentypen enthält.

Nachdem ein serialisiertes Objekt in eine Datei geschrieben wurde, kann es aus der Datei gelesen und deserialisiert werden, dh die Typinformationen und Bytes, die das Objekt und seine Daten darstellen, können verwendet werden, um das Objekt im Speicher neu zu erstellen.

Wenn Sie ein Tutorial dazu wünschen, verweisen Sie auf diesen Link

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

Variable in anderen Klassen abrufen

D. CommonUtilities

Sie können selbst eine Klasse erstellen, die allgemeine Daten enthalten kann, die Sie häufig in Ihrem Projekt benötigen.

Stichprobe

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Weitergabe von Daten durch Absichten

In diesem Tutorial finden Sie Informationen zum Übergeben von Daten.

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

Nikhil Agrawal
quelle
Gutes Tutorial, das Sie in (E) zum Weiterleiten von Daten durch Absichten erwähnen.
Remrick
15

Vielen Dank für die Hilfe bei Paketen, aber ich habe eine weitere optionale Lösung gefunden

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

In Aktivität Eins

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

Daten in Aktivität 2 abrufen

 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());
        }
Benutzer1140237
quelle
1
Gute Antwort, aber erhöhen Sie Ihre Codierungsstandards ... +1, um Serializable in die Konkurrenz zu bringen, aber Parcellables sind viel schneller ...
Amit
13

Ich benutze Gson mit seiner so mächtigen und einfachen API, um Objekte zwischen Aktivitäten zu senden.

Beispiel

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

Mit 2 Funktionen fügen Sie sie den Objekten hinzu, die Sie senden möchten

Verwendungszweck

Objekt von A nach B senden

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

In B empfangen

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

Ich benutze es fast in jedem Projekt, das ich mache, und ich habe keine Leistungsprobleme.

MBH
quelle
Danke, das hat mir Stunden der Überkomplikation erspart.
Hristo Stoyanov
10

Ich hatte mit dem gleichen Problem zu kämpfen. Ich habe es mithilfe einer statischen Klasse gelöst und alle gewünschten Daten in einer HashMap gespeichert. Darüber hinaus verwende ich eine Erweiterung der Standard-Aktivitätsklasse, in der ich die Methoden onCreate an onDestroy überschrieben habe, um den Datentransport und die Datenlöschung versteckt durchzuführen. Einige lächerliche Einstellungen müssen geändert werden, z. B. Orientierungshandhabung.

Anmerkung: Das Nicht-Bereitstellen allgemeiner Objekte, die an eine andere Aktivität weitergegeben werden sollen, ist ein Schmerz im Arsch. Es ist, als würde man sich ins Knie schießen und hoffen, 100 Meter zu gewinnen. "Parcable" ist kein ausreichender Ersatz. Es bringt mich zum Lachen ... Ich möchte diese Schnittstelle nicht in meine technologiefreie API implementieren, da ich weniger eine neue Ebene einführen möchte ... Wie könnte es sein, dass wir in der mobilen Programmierung so weit weg sind modernes Paradigma ...

oopexpert
quelle
9

In Ihrer ersten Aktivität:

intent.putExtra("myTag", yourObject);

Und in deinem zweiten:

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

Vergessen Sie nicht, Ihr benutzerdefiniertes Objekt serialisierbar zu machen:

public class myCustomObject implements Serializable {
...
}
Rudi
quelle
Paket ist besser als serialisierbar! Vermeiden Sie es, Serializable in Ihrem Android-Code zu verwenden!
Filipe Brito
7

Eine andere Möglichkeit, dies zu tun, besteht darin, das ApplicationObjekt (android.app.Application) zu verwenden. Sie definieren dies in Ihrer AndroidManifest.xmlDatei als:

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

Sie können dies dann von jeder Aktivität aus aufrufen und das Objekt in der ApplicationKlasse speichern .

In der FirstActivity:

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

Führen Sie in der zweiten Aktivität Folgendes aus:

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

Dies ist praktisch, wenn Sie Objekte mit Anwendungsbereich haben, dh sie müssen in der gesamten Anwendung verwendet werden. Die ParcelableMethode ist immer noch besser, wenn Sie eine explizite Kontrolle über den Objektbereich wünschen oder wenn der Bereich begrenzt ist.

Dies vermeidet jedoch die Verwendung von Intentsinsgesamt. Ich weiß nicht, ob sie zu dir passen. Eine andere Möglichkeit, die ich verwendet habe, besteht darin, intBezeichner von Objekten durch Absichten senden zu lassen und Objekte abzurufen, die ich in Maps im ApplicationObjekt habe.

Saad Farooq
quelle
1
Es ist nicht der richtige Weg, Dinge zu tun, da die Objekte variabel sein können. Ihre können funktionieren, wenn Sie über statische Objekte während des Lebenszyklus der App sprechen. Manchmal müssen wir jedoch Objekte übergeben, die möglicherweise über den Webservice oder so über stackoverflow.com generiert wurden / a / 2736612/716865
Muhannad A.Alhariri
Ich habe es erfolgreich mit Objekten verwendet, die aus Webservices generiert wurden, indem ich einen Anwendungsbereich hatte, Mapin dem die Objekte mithilfe eines Bezeichners gespeichert und abgerufen werden. Das einzige wirkliche Problem bei diesem Ansatz ist, dass Android nach einer Weile den Speicher löscht, sodass Sie in Ihrem onResume nach Nullen suchen müssen (ich denke, dass Objekte, die in Absichten übergeben wurden, bestehen bleiben, aber nicht sicher sind). Abgesehen davon sehe ich dies nicht als wesentlich minderwertig an.
Saad Farooq
Dies ist die beste Antwort. Es zeigt, wie verschiedene Aktivitäten auf dasselbe Datenmodell verweisen können. Ich habe viel zu lange gebraucht, um das zu entdecken!
Markus
6

Implementieren Sie in Ihrem Klassenmodell (Objekt) Serializable, zum Beispiel:

public class MensajesProveedor implements Serializable {

    private int idProveedor;


    public MensajesProveedor() {
    }

    public int getIdProveedor() {
        return idProveedor;
    }

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


}

und deine erste Aktivität

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

und Ihre zweite Aktivität (NewActivity)

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

Viel Glück!!

David Hackro
quelle
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];
        }
    };

}

Daten übergeben:

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

Daten abrufen:

Bundle bundle = getIntent().getExtras();
dataList2 = getIntent().getExtras().getParcelableArrayList("data");
Adnan Abdollah Zaki
quelle
5

Die einfachste Lösung, die ich gefunden habe, ist .. eine Klasse mit statischen Datenelementen mit Getter-Setzern zu erstellen.

Setze von einer Aktivität und erhalte von einer anderen Aktivität dieses Objekt.

Aktivität A.

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

Aktivität b

mytestclass obj= mytestclass.staticfunctionGet();
UMAR
quelle
1
oder eine serialisierbare Klasse erstellen, um sie an eine andere Aktivität zu übergeben, was auch immer Sie übergeben möchten.
UMAR
9
Denken Sie daran, keine großen, fetten Gegenstände zu platzieren. Die Lebensdauer dieses Objekts entspricht der Lebensdauer der Anwendung. Und niemals Ansichten speichern. Diese Methode garantiert auch Speicherlecks.
Reno
1
Diese Antwort ist nützlich, aber keine bessere Lösung in Bezug auf Speicher- und Ressourcenoptimierung
Atul Bhardwaj
1
Dies bricht die OOP-Prinzipien, indem globale Variablen eingeführt werden. Man weiß nie, in welchem ​​Zustand sie sich befinden, ob sie gesetzt sind oder nicht, sie werden von vielen Threads verwendet und man muss sich mit dieser Komplexität auseinandersetzen. Es ist normalerweise ein guter Speicherverlust, da Sie nicht einmal wissen, wann Sie diese Variablen freigeben müssen. Um nicht zu sagen, dass es eine harte direkte Kopplung zwischen verschiedenen Modulen der Anwendung einführt.
Afrika
2
WTF? Die anderen beiden Antworten sind viel besser.
IcyFlame
4

Sie können die Methoden putExtra (Serializable ..) und getSerializableExtra () verwenden, um Objekte Ihres Klassentyps zu übergeben und abzurufen. Sie müssen Ihre Klasse Serializable markieren und sicherstellen, dass alle Ihre Mitgliedsvariablen auch serialisierbar sind ...

Null
quelle
4

Erstellen Sie eine Android-Anwendung

Datei >> Neu >> Android-Anwendung

Geben Sie den Projektnamen ein: android-pass-object-to-activity

Pakcage: com.hmkcode.android

Behalten Sie andere Auswahlmöglichkeiten bei, gehen Sie zu Weiter, bis Sie Fertig stellen erreichen

Bevor wir mit der Erstellung der App beginnen, müssen wir die POJO-Klasse „Person“ erstellen, mit der wir Objekte von einer Aktivität zu einer anderen senden. Beachten Sie, dass die Klasse eine serialisierbare Schnittstelle implementiert.

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 + "]";
    }   
}

Zwei Layouts für zwei Aktivitäten

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>

Zwei Aktivitätsklassen

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
quelle
4

Mit der Gson-Bibliothek von Google können Sie Objekte an andere Aktivitäten übergeben. Tatsächlich konvertieren wir Objekte in Form von JSON-Zeichenfolgen und konvertieren sie nach Übergabe an andere Aktivitäten erneut in Objekte wie diese

Betrachten Sie eine Bean-Klasse wie diese

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

Wir müssen das Objekt der Beispielklasse übergeben

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

Zum Lesen müssen wir in NextActivity den umgekehrten Vorgang ausführen

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

Fügen Sie diese Abhängigkeit in Gradle hinzu

compile 'com.google.code.gson:gson:2.6.2'
Jinesh Francis
quelle
3
Intent i = new Intent();
i.putExtra("name_of_extra", myParcelableObject);
startACtivity(i);
Manas Ranjan
quelle
3

Ich weiß, dass dies spät ist, aber es ist sehr einfach. Alles, was Sie tun müssen, ist, Ihre Klasse Serializable wie implementieren zu lassen

public class MyClass implements Serializable{

}

dann können Sie zu einer Absicht wie übergehen

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

Um es zu bekommen, rufst du einfach an

MyClass objec=(MyClass)intent.getExtra("theString");
Suulisin
quelle
2

Wenn Sie eine Singleton-Klasse (fx Service) haben, die ohnehin als Gateway zu Ihrer Modellebene fungiert, kann dies gelöst werden, indem in dieser Klasse eine Variable mit Get- und Setter-Elementen vorhanden ist.

In Aktivität 1:

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

In Aktivität 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.
}

Im Dienst:

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

Diese Lösung erfordert keine Serialisierung oder andere "Verpackung" des betreffenden Objekts. Es ist jedoch nur dann von Vorteil, wenn Sie diese Art von Architektur verwenden.

Kitalda
quelle
Was sind die Nachteile dieses Ansatzes? Es scheint so logisch und schlank. Ich habe immer gelesen, dass Sie das nicht tun sollten, aber ich bekomme nie eine gute Erklärung dafür, was schief gehen könnte.
Markus
Da ich meinen Kommentar nicht mehr bearbeiten kann: Ist dies nicht die einzig mögliche Lösung, um einen Verweis auf ein Objekt anstelle einer Kopie zu erhalten? Ich muss das gleiche Objekt abrufen und keine Kopie!
Markus
Ich denke, dies wird aufgrund der hohen Kopplung, zu der es führt, etwas entmutigt. Aber ja, soweit ich sehen kann, ist dieser Ansatz am sinnvollsten, wenn Sie das eigentliche Objekt benötigen. Wie immer in der Programmierung können Sie tun, was Sie wollen, Sie wollen es nur vorsichtig tun. Diese Lösung hat bei mir funktioniert und ich bevorzuge sie, da ich diese Architektur sowieso verwende.
Kitalda
Eigentlich habe ich die Application-Klasse erweitert und mein Datenmodell dort gespeichert. In den Absichten habe ich nur die ID der Datenobjekte weitergeleitet, mit denen das ursprüngliche Objekt aus der Anwendungsklasse abgerufen werden konnte. Außerdem benachrichtigt die erweiterte Anwendungsklasse alle Objekte, die das Datenmodell verwenden, wenn es sich über ein Standard-Listener-Konzept ändert. Ich weiß, dass dies nur für meinen Fall passt, in dem ich ein Datenmodell für die gesamte Anwendung freigeben muss, aber für diesen Fall ist es perfekt und es werden auch keine statischen Klassen und Felder benötigt!
Markus
2

IMHO bei weitem der einfachste Weg, Objekte zu paketieren. Sie fügen einfach ein Anmerkungs-Tag über dem Objekt hinzu, das Sie paketierbar machen möchten.

Ein Beispiel aus der Bibliothek finden Sie unter 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
quelle
2

Implementieren Sie zuerst Parcelable in Ihrer Klasse. Dann übergeben Sie das Objekt wie folgt.

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

Die Paketzeichenfolge ist nicht erforderlich, nur die Zeichenfolge muss in beiden Aktivitäten identisch sein

REFERENZ

Arpit Patel
quelle
2

Starten Sie eine andere Aktivität von diesem Aktivitätsübergabeparameter über Bundle Object

Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "[email protected]");
startActivity(intent);

Bei einer anderen Aktivität abrufen (YourActivity)

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

Dies ist für einfache Datentypen in Ordnung. Wenn Sie jedoch komplexe Daten zwischen den Aktivitäten übergeben möchten, müssen Sie diese zuerst serialisieren.

Hier haben wir das Mitarbeitermodell

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

    getters...
    setters...
}

Sie können die von Google bereitgestellte Gson lib verwenden, um die komplexen Daten wie folgt zu serialisieren

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);
Benutzer1101821
quelle
2

In Koltin

Fügen Sie die Kotlin-Erweiterung in Ihr build.gradle ein.

apply plugin: 'kotlin-android-extensions'

android {
    androidExtensions {
        experimental = true
   }
}

Erstellen Sie dann Ihre Datenklasse wie folgt.

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

Objekt mit Absicht übergeben

val sample = Sample(1,"naveen")

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

Objekt mit Absicht abrufen

val sample = intent.getParcelableExtra("id")
Naveen
quelle
Ist es noch experimentell?
ShadeToD
2

Die einfachste und Java-Methode ist: Implementieren Sie serialisierbar in Ihrer Pojo / Modellklasse

Empfohlen für Android für die Leistungsansicht: Modell paketierbar machen

Ashok Kumar
quelle
1

Am einfachsten wäre es, nur Folgendes zu verwenden, wenn das Element eine Zeichenfolge ist:

intent.putextra("selected_item",item)

Für den Empfang:

String name = data.getStringExtra("selected_item");
ankish
quelle
3
Es ist nur für String, Integer und etc, aber ich möchte das Objekt und mit statischen Objekt ist es nur möglich.
UMAR