So übergeben Sie ein Objekt unter Android von einer Aktivität an eine andere


779

Ich versuche, ein Objekt meiner Kundenklasse von einem zu senden Activityund in einem anderen anzuzeigen Activity.

Der Code für die Kundenklasse:

public class Customer {

    private String firstName, lastName, Address;
    int Age;

    public Customer(String fname, String lname, int age, String address) {

        firstName = fname;
        lastName = lname;
        Age = age;
        Address = address;
    }

    public String printValues() {

        String data = null;

        data = "First Name :" + firstName + " Last Name :" + lastName
        + " Age : " + Age + " Address : " + Address;

        return data;
    }
}

Ich möchte sein Objekt von einem Activityzum anderen senden und dann die Daten auf dem anderen anzeigen Activity.

Wie kann ich das erreichen?


1
wahrscheinlich sollten Sie die akzeptierte Antwort im Hinblick auf die Massenmeinung ändern.
Rohit Vipin Mathews

Früher habe ich das Objekt auf Pacelable oder Serializable gesetzt, aber wenn ich andere Variablen hinzufüge, muss ich alles zu Funktionen hinzufügen, um Pacelable oder Serializable abzurufen und festzulegen. Also habe ich DataCache für die Übertragung zwischen Aktivitäten und Fragmenten erstellt. github.com/kimkevin/AndroidDataCache Das Übertragen von Objekten ist sehr einfach.
Kimkevin

Antworten:


886

Eine Option könnte darin bestehen, dass Ihre benutzerdefinierte Klasse die SerializableSchnittstelle implementiert , und Sie können dann Objektinstanzen in der Absicht extra mit der putExtra(Serializable..)Variante der Intent#putExtra()Methode übergeben.

Pseudocode :

//To pass:
intent.putExtra("MyClass", obj);

// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");

Hinweis: Stellen Sie sicher, dass jede verschachtelte Klasse Ihrer benutzerdefinierten Hauptklasse eine serialisierbare Schnittstelle implementiert hat, um Serialisierungsausnahmen zu vermeiden. Zum Beispiel:

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}

126
@OD: Zu meiner Verteidigung habe ich nie gesagt, dass dies die beste Option ist. OP hat nur nach Alternativen gefragt und ich habe eine vorgeschlagen. Trotzdem danke.
Samuh

83
Warum ist Serializable keine gute Option? Es ist eine bekannte Schnittstelle, es besteht eine gute Chance, dass die Klassen der Leute sie bereits implementieren (ArrayList ist beispielsweise bereits serialisierbar). Warum sollten Sie Ihre Datenobjekte ändern müssen, um zusätzlichen Code hinzuzufügen, um sie einfach von einer Klasse an eine andere zu übergeben? Das scheint ein schlechtes Design zu sein. Ich kann mir vorstellen, dass es auf einer bestimmten Ebene zu Leistungseinbußen kommen kann, aber ich würde denken, dass in 99% der Fälle kleine Datenmengen weitergegeben werden und es ihnen egal ist. Einfacher und tragbarer ist manchmal auch besser.
Nate

16
@Sander: Ist diese Antwort ( stackoverflow.com/questions/2139134/… ) dann falsch? Er sagt, dass Parcelable IS speziell für diesen Zweck entwickelt wurde (und viel schneller als Serializable). Ich bin verwirrt.
Slauma

41
Parcelablemag gut für die Geschwindigkeit sein, aber es ist kompliziert zu implementieren. Was ist, wenn Sie 8 Objekte haben, die Sie zwischen den Aktivitäten übergeben müssen Parcelable? Werden Sie jedes einzelne erstellen ? Es wäre sinnvoller, Serializablestattdessen zu verwenden . Wenn Sie implementieren Parcelable, müssen Sie der Klasse viel Code hinzufügen und Felder auf eine ganz bestimmte Weise ordnen. Serializabledu nicht. Letztendlich denke ich, dass es darauf ankommt, wie viele Objekte Sie passieren und was Sie versuchen zu tun.
BlackHatSamurai

15
Serializableist eine Standard-Java-Schnittstelle. Sie markieren einfach eine Klasse Serializable, indem Sie die Schnittstelle implementieren, und Java serialisiert sie in bestimmten Situationen automatisch. Parcelableist eine Android-spezifische Schnittstelle, über die Sie die Serialisierung selbst implementieren. Es wurde entwickelt, um weitaus effizienter als Serializable zu sein und um einige Probleme mit dem Standard-Java-Serialisierungsschema zu umgehen
Gaurav Arora

311

Implementieren Sie Ihre Klasse mit Serializable. Nehmen wir an, dies ist Ihre Entitätsklasse:

import java.io.Serializable;

@SuppressWarnings("serial") //With this annotation we are going to hide compiler warnings
public class Deneme implements Serializable {

    public Deneme(double id, String name) {
        this.id = id;
        this.name = name;
    }

    public double getId() {
        return id;
    }

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

    public String getName() {
        return this.name;
    }

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

    private double id;
    private String name;
}

Wir senden das denevon X-Aktivität aufgerufene Objekt an Y-Aktivität. Irgendwo in X-Aktivität;

Deneme dene = new Deneme(4,"Mustafa");
Intent i = new Intent(this, Y.class);
i.putExtra("sampleObject", dene);
startActivity(i);

In der Y-Aktivität erhalten wir das Objekt.

Intent i = getIntent();
Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");

Das ist es.


1
Es war sehr hilfreich für mich. Danke ... Aber beim Empfang des übergebenen Objekts sollte die Syntax [Deneme dene = (Deneme) i.getSerializableExtra ("sampleObject") sein; ] ... Ist es ???
JibW

1
@ MustafaGüven Aber ich komme damit klar classCastException: java.lang.Long. Können Sie bitte erklären, warum?
Shajeel Afzal

Es gibt keine Beziehung zu meiner Antwort. Es ist eine ganz andere Sache, die Sie bekommen. Könnten Sie Ihre Codes teilen?
Mustafa Güven

1
Serializable ist für große POJOs zu langsam. Die Verwendung eines Busses ist ein viel besseres Muster.
Steven Mark Ford

1
Warum sollte ich (Serializable)dem Objekt ein Präfix voranstellen müssen ?
Alston

123
  • Die Verwendung globaler statischer Variablen ist keine gute Softwareentwicklungspraxis .
  • Das Konvertieren der Felder eines Objekts in primitive Datentypen kann eine hektische Aufgabe sein .
  • Die Verwendung von serialisierbar ist in Ordnung, auf der Android-Plattform jedoch nicht leistungswirksam .
  • Parcelable wurde speziell für Android entwickelt und sollte verwendet werden. Hier ein einfaches Beispiel: Übergeben von benutzerdefinierten Objekten zwischen Android-Aktivitäten

Über diese Site können Sie Paketcode für Ihre Klasse generieren .


4
Was ist, wenn mein Objekt eine verschachtelte Arrayliste enthält?
Dr. aNdRO

10
Nun, vielleicht, aber man sollte wirklich "Leistung" mit einem Körnchen Salz imo nehmen. Wenn dies zu Lasten der Implementierung geht, Parcelablemöchte ich meine POJO-Klassen lieber Android-unabhängig halten und verwenden Serializable.
VH-NZZ

Ich bin nicht der Meinung, dass Sie Parcelable verwenden sollten. Ein einfaches BUS-Muster ist zur Laufzeit viel effizienter und spart eine Menge Entwicklungszeit.
Steven Mark Ford

15
Nach diesem Benchmark ist bitbucket.org/afrishman/androidserializationtest Serializable viel schneller als Parcelable. Bitte hören Sie auf, diesen 5 Jahre alten Unsinn über Parcelable zu teilen.
Afrika

7
Wie sind globale statische Variablen "keine gute Softwareentwicklungspraxis"? Sie können so etwas wie einen Singleton-Cache und / oder ein Datenraster erstellen und dann IDs oder ähnliches weitergeben. Wenn Sie Referenzen in Java weitergeben, verwenden Sie ohnehin globale statische Variablen, da diese auf dasselbe Objekt verweisen.
Bruchlinie

112

Verwenden Sie gson , um Ihr Objekt in JSON zu konvertieren und es zu übergeben. Konvertieren Sie in der neuen Aktivität den JSON in ein Objekt.

Fügen build.gradleSie dies in Ihren Abhängigkeiten hinzu

implementation 'com.google.code.gson:gson:2.8.4'

Konvertieren Sie in Ihrer Aktivität das Objekt in json-string:

Gson gson = new Gson();
String myJson = gson.toJson(vp);
intent.putExtra("myjson", myjson);

Konvertieren Sie in Ihrer empfangenden Aktivität den JSON-String zurück in das ursprüngliche Objekt:

Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);

Für Kotlin ist es genauso

Übergeben Sie die Daten

val gson = Gson()
val intent = Intent(this, YourActivity::class.java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)

Erhalten Sie die Daten

val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.java)

3
Es ist ein Overkill, gson ist nur eine Art von String-Serialisierung für json. Es ist besser, Serializable oder Paracable zu implementieren.
James Roeiter

14
Es ist nicht erforderlich, serialisierbar in jedem Objekt und in jedem Projekt zu implementieren (Zeitverschwendung), wenn Sie eine Bibliothek (gson) verwenden können, die dies handhabt. Und was Overkill betrifft, so gibt es Dual- und Quadcore-Telefone, die nach dieser Antwortidee sogar eine Liste erstellen können.
Sagits

4
Ich würde auch die Verwendung von gson empfehlen, da gson zusätzlich zu den oben genannten auch Arraylisten serialisieren kann.
Nurgasemetey

4
Das ist toll! In meinem Fall verwende ich eine Bibliothek, die von den Objekten nicht serialisierbar oder paketierbar implementiert wird. Das ist also meine einzige Option afaik
Chad Bingham

2
Dies ist die "beste" Option. Einige Klassen sind so einfach, dass Sie ihre Implementierung nicht zu kompliziert machen müssen, indem Sie serialisierbar implementieren
Ojonugwa Jude Ochalifu

98

Beim Aufrufen einer Aktivität

Intent intent = new Intent(fromClass.this,toClass.class).putExtra("myCustomerObj",customerObj);

In toClass.java erhalten Sie die Aktivität von

Customer customerObjInToClass = getIntent().getExtras().getParcelable("myCustomerObj");

Bitte stellen Sie sicher, dass die Kundenklasse paketfähig implementiert

public class Customer implements Parcelable {

    private String firstName, lastName, address;
    int age;

    /* all your getter and setter methods */

    public Customer(Parcel in ) {
        readFromParcel( in );
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public LeadData createFromParcel(Parcel in ) {
            return new Customer( in );
        }

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


    @Override
    public void writeToParcel(Parcel dest, int flags) {

        dest.writeString(firstName);
        dest.writeString(lastName);
        dest.writeString(address);
        dest.writeInt(age);
    }

    private void readFromParcel(Parcel in ) {

        firstName = in .readString();
        lastName  = in .readString();
        address   = in .readString();
        age       = in .readInt();
    }

Adhavan, ich habe eine Frage. Wenn Sie die erste Intent-Klasse erstellen, übergeben Sie fromClass.this als erstes Argument. Gibt es eine Möglichkeit, dieses Objekt in der empfangenden Aktivitätsklasse abzurufen?
Newman

1
Miliu, fromClass fr = (fromClass) getParent (); brauchst du das?
Anzeigen

Adhava, ich habe das tatsächlich gemacht, aber fr ist null. Irgendeine Idee warum?
Newman

miliu, bitte teile deine ausnahmespur mit, damit wir sie untersuchen können.
Anzeigen

Parcelable hat eine Menge unnötiger Kesselplattencodes und ist ehrlich gesagt Zeitverschwendung. Benutze lieber einen Bus. Siehe meinen Beitrag unten.
Steven Mark Ford

89

Nach meiner Erfahrung gibt es drei Hauptlösungen mit jeweils ihren Nachteilen und Vorteilen:

  1. Paket implementieren

  2. Serializable implementieren

  3. Verwenden einer leichten Ereignisbusbibliothek (z. B. EventBus von Greenrobot oder Otto von Square)

Parcelable - schnell und Android-Standard, aber es hat viel Boilerplate-Code und erfordert hartcodierte Zeichenfolgen als Referenz, wenn Werte aus der Absicht herausgezogen werden (nicht stark typisiert).

Serialisierbar - nahe Null, aber es ist der langsamste Ansatz und erfordert auch hartcodierte Zeichenfolgen, wenn Werte aus der Absicht herausgezogen werden (nicht stark typisiert).

Event Bus - Null-Boilerplate, schnellster Ansatz und erfordert keine fest codierten Zeichenfolgen, erfordert jedoch eine zusätzliche Abhängigkeit (obwohl normalerweise leichtgewichtig, ~ 40 KB)

Ich habe einen sehr detaillierten Vergleich dieser drei Ansätze veröffentlicht, einschließlich Effizienz-Benchmarks.


4
Der Link zum Artikel ist tot. Noch verfügbar auf webarchive: web.archive.org/web/20160917213123/http://…
OlivierH

Es ist eine Schande, dass der Link nicht
funktioniert

Das Problem bei der Verwendung des Ereignisbusses besteht darin, dass die Zielaktivität beispielsweise aufgrund von Rotation neu erstellt wird. In diesem Fall hat die Zielaktivität keinen Zugriff auf das übergebene Objekt, da dieses Objekt durch einen früheren Aufruf vom Bus verbraucht wurde.
JuliuszJ

1
Parcelable ist am schnellsten und mit diesem Generator ( parcelabler.com ) können Sie Ihre Klasse einfügen und den Code für Sie generieren. Einfach.
ByWaleed

1
@ByWaleed ... Ich stimme absolut zu, ich benutze immer diese Seite, mache Sachen ohne Probleme. Ich hatte jedoch viele erfolglose Versuche, als ich versuchte, ein POJO zu verwenden, das aus einem anderen Objekt besteht. Aus irgendeinem Grund funktioniert die Ausgabe nicht wirklich.
Yo Apps

42

Ich habe eine einfache und elegante Methode gefunden:

  • KEIN Paket
  • NEIN Serialisierbar
  • KEIN statisches Feld
  • Kein Ereignisbus

Methode 1

Code für die erste Aktivität:

    final Object objSent = new Object();
    final Bundle bundle = new Bundle();
    bundle.putBinder("object_value", new ObjectWrapperForBinder(objSent));
    startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));        
    Log.d(TAG, "original object=" + objSent);

Code für die zweite Aktivität:

    final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
    Log.d(TAG, "received object=" + objReceived);

Sie werden das gleiche finden objSentund objReceivedhabenhashCode , so dass sie identisch sind.

Aber warum können wir auf diese Weise ein Java-Objekt übergeben?

Tatsächlich erstellt Android Binder eine globale JNI-Referenz für das Java-Objekt und gibt diese globale JNI-Referenz frei, wenn für dieses Java-Objekt keine Referenz vorhanden ist. Binder speichert diese globale JNI-Referenz im Binder-Objekt.

* VORSICHT: Diese Methode funktioniert NUR, es sei denn, die beiden Aktivitäten werden im selben Prozess ausgeführt. Andernfalls wird ClassCastException unter (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") ausgelöst. *

Klasse ObjectWrapperForBinder Definition

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

    public ObjectWrapperForBinder(Object data) {
        mData = data;
    }

    public Object getData() {
        return mData;
    }
}

Methode 2

  • für den Absender
    1. Verwenden Sie eine benutzerdefinierte native Methode, um Ihr Java-Objekt zur globalen JNI-Referenztabelle hinzuzufügen (über JNIEnv :: NewGlobalRef).
    2. Setzen Sie die Rückgabe-Ganzzahl (eigentlich JNIEnv :: NewGlobalRef return jobject, ein Zeiger, den wir sicher in int umwandeln können) in Ihre Absicht (über Intent :: putExtra).
  • für den Empfänger
    1. Ganzzahl von Intent abrufen (über Intent :: getInt)
    2. Verwenden Sie eine benutzerdefinierte native Methode, um Ihr Java-Objekt aus der globalen JNI-Referenztabelle wiederherzustellen (über JNIEnv :: NewLocalRef).
    3. Element aus der globalen JNI-Referenztabelle entfernen (über JNIEnv :: DeleteGlobalRef),

Methode 2 hat jedoch ein kleines, aber schwerwiegendes Problem: Wenn der Empfänger das Java-Objekt nicht wiederherstellen kann (z. B. tritt vor der Wiederherstellung des Java-Objekts eine Ausnahme auf oder die Empfängeraktivität überhaupt nicht vorhanden ist), wird das Java-Objekt zu einem Orphan oder Speicherverlust, Methode 1 hat dieses Problem nicht, da Android Binder diese Ausnahme behandelt

Methode 3

Um das Java-Objekt remote aufzurufen, erstellen wir einen Datenvertrag / eine Datenschnittstelle zur Beschreibung des Java-Objekts. Wir verwenden die Hilfedatei

IDataContract.aidl

package com.example.objectwrapper;
interface IDataContract {
    int func1(String arg1);
    int func2(String arg1);
}

Code für die erste Aktivität

    final IDataContract objSent = new IDataContract.Stub() {

        @Override
        public int func2(String arg1) throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "func2:: arg1=" + arg1);
            return 102;
        }

        @Override
        public int func1(String arg1) throws RemoteException {
            // TODO Auto-generated method stub
            Log.d(TAG, "func1:: arg1=" + arg1);
            return 101;
        }
    };
    final Bundle bundle = new Bundle();
    bundle.putBinder("object_value", objSent.asBinder());
    startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));
    Log.d(TAG, "original object=" + objSent);

Code für die zweite Aktivität:

Ändern Sie das android: process-Attribut in AndroidManifest.xml in einen nicht leeren Prozessnamen, um sicherzustellen, dass die zweite Aktivität in einem anderen Prozess ausgeführt wird

    final IDataContract objReceived = IDataContract.Stub.asInterface(getIntent().getExtras().getBinder("object_value"));
    try {
        Log.d(TAG, "received object=" + objReceived + ", func1()=" + objReceived.func1("test1") + ", func2()=" + objReceived.func2("test2"));
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Auf diese Weise können wir eine Schnittstelle zwischen zwei Aktivitäten übergeben, obwohl diese in unterschiedlichen Prozessen ausgeführt werden, und die Schnittstellenmethode remote aufrufen

Methode 4

Methode 3 scheint nicht einfach genug zu sein, da wir eine Hilfeschnittstelle implementieren müssen. Wenn Sie nur eine einfache Aufgabe ausführen möchten und der Rückgabewert der Methode nicht erforderlich ist, können wir android.os.Messenger verwenden

Code für die erste Aktivität (Absender):

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";

    public static final int MSG_OP1 = 1;
    public static final int MSG_OP2 = 2;

    public static final String EXTRA_MESSENGER = "messenger";

    private final Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            Log.e(TAG, "handleMessage:: msg=" + msg);
            switch (msg.what) {
            case MSG_OP1:

                break;
            case MSG_OP2:
                break;

            default:

                break;
            }
            super.handleMessage(msg);
        }

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

        startActivity(new Intent(this, SecondActivity.class).putExtra(EXTRA_MESSENGER, new Messenger(mHandler)));
    }
}

Code für die zweite Aktivität (Empfänger):

public class SecondActivity extends Activity {

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

        final Messenger messenger = getIntent().getParcelableExtra(MainActivity.EXTRA_MESSENGER);
        try {
            messenger.send(Message.obtain(null, MainActivity.MSG_OP1, 101, 1001, "10001"));
            messenger.send(Message.obtain(null, MainActivity.MSG_OP2, 102, 1002, "10002"));
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

Alle Messenger.send werden asynchron und sequentiell in einem Handler ausgeführt.

Tatsächlich ist android.os.Messenger auch eine Hilfeschnittstelle. Wenn Sie den Android-Quellcode haben, finden Sie eine Datei mit dem Namen IMessenger.aidl

package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
    void send(in Message msg);
}

Entschuldigung, ich habe nicht gesehen, dass Sie auch in Ihrer Antwort verbindlich waren. Ich finde, dass Ihre Antwort auch sehr elegant ist.
SkidRunner

Wow .... Die erste Methode dieses Mannes ist enorm ..... Wenn Sie sehr große / größere Objekte haben, die gut funktionieren
Karan

Ich Benutzer Methode eins. Also, Sie sparen meine Zeit. Vielen Dank;
ShweLiam

Vielen Dank für die ObjectWrapperForBinder-Methode, die wirklich hilft!
Vladimir Tolstikov

40

Sie können die Daten des Objekts auch in temporäre Zeichenfolgen und Ints schreiben und an die Aktivität übergeben. Auf diese Weise erhalten Sie natürlich die Daten, aber nicht das Objekt selbst.

Wenn Sie sie jedoch nur anzeigen und das Objekt nicht in einer anderen Methode oder ähnlichem verwenden möchten, sollte dies ausreichen. Ich habe es genauso gemacht, nur Daten von einem Objekt in einer anderen Aktivität anzuzeigen.

String fName_temp   = yourObject.getFname();
String lName_temp   = yourObject.getLname();
String age_temp     = yourObject.getAge();
String address_temp = yourObject.getAddress();

Intent i = new Intent(this, ToClass.class);
i.putExtra("fname", fName_temp);
i.putExtra("lname", lName_temp);
i.putExtra("age", age_temp);
i.putExtra("address", address_temp);

startActivity(i);

Sie könnten sie auch direkt anstelle der temporären Ivars weitergeben, aber auf diese Weise ist es meiner Meinung nach klarer. Darüber hinaus können Sie die temporären ivars auf null setzen, damit sie früher vom GarbageCollector bereinigt werden.

Viel Glück!

Nebenbei bemerkt: Überschreiben Sie toString (), anstatt Ihre eigene Druckmethode zu schreiben.

Wie in den Kommentaren unten erwähnt, erhalten Sie Ihre Daten auf diese Weise in einer anderen Aktivität zurück:

String fName = getIntent().getExtras().getInt("fname");

9
Holen Sie Ihre Daten wieder zurück mit: String fName = getIntent (). getExtras (). getInt ("fname");
Alister

2
Um die Daten zurückzubekommen: Bundle extras = getIntent().getExtras(); String val = extras.getString("fname");
Eric Leschinski

1
Dies kann für große POJOs schnell unmöglich werden. Benutze lieber einen Bus. Siehe meinen Beitrag unten.
Steven Mark Ford

Wie ich in meiner Antwort erwähnt habe, ist dies für einfache Fälle gedacht, in denen Sie das Objekt selbst nicht benötigen, sondern nur einige Werte davon. Es ist keine Erwähnung, eine Lösung für komplexe Anwendungsfälle zu sein.
MJB

1
Gute Idee, ein einzelnes Objekt zu übergeben, aber ich versuche, ein Array unbekannter Größe meines Objekts zu übergeben. Möglicherweise besteht Ihre Lösung nicht darin, Objektarrays zu übergeben.
Muhammad Saqib

25

Ich habe eine Singleton-Hilfsklasse erstellt, die temporäre Objekte enthält.

public class IntentHelper {

    private static IntentHelper _instance;
    private Hashtable<String, Object> _hash;

    private IntentHelper() {
        _hash = new Hashtable<String, Object>();
    }

    private static IntentHelper getInstance() {
        if(_instance==null) {
            _instance = new IntentHelper();
        }
        return _instance;
    }

    public static void addObjectForKey(Object object, String key) {
        getInstance()._hash.put(key, object);
    }

    public static Object getObjectForKey(String key) {
        IntentHelper helper = getInstance();
        Object data = helper._hash.get(key);
        helper._hash.remove(key);
        helper = null;
        return data;
    }
}

Verwenden Sie IntentHelper, anstatt Ihre Objekte in Intent zu platzieren:

IntentHelper.addObjectForKey(obj, "key");

In Ihrer neuen Aktivität können Sie das Objekt abrufen:

Object obj = (Object) IntentHelper.getObjectForKey("key");

Beachten Sie, dass das Objekt nach dem Laden entfernt wird, um unnötige Verweise zu vermeiden.


1
Gute Idee! Zusätzlich können Sie möglicherweise eine zusätzliche Klasse ObjectContainer {Object, obj; boolesche bleibende; ....} Die Idee ist, dass Sie einen Booleschen Wert in der add-Methode übergeben können, wenn Sie das Objekt persistent halten und nicht entfernen müssen, wenn wir get aufrufen. Es wird helfen, einige globale Objekte zu behalten. Wie kann eine offene Bluetooth-Verbindung usw. sein
Umair

1
Süß, aber das Rad nicht neu erfinden. Das Busmuster ist elegant und leistungsfähiger. Siehe meinen Beitrag unten.
Steven Mark Ford

@StevenMarkFord Also gilt das Bus-Muster bis heute? Ich versuche, eine Codebasis mit einem Code wie diesem zu verbessern, der auf Daten zwischen Aktivitäten zugreift: BookActivity.getInstance().recommendationResponseinRoomsActivity
Woppi

Wenn die empfangende Aktivität neu erstellt wird (z. B. bei Bildschirmdrehung) objwird null. Um dies zu vermeiden, objsollte irgendwo gelagert werden, um es wieder zu bekommen. In der Tat speichert die Json-Lösung Objektdaten in Intent.
Salvador

25

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 allgemeine Dienstprogramme bezeichnet werden. Es hängt von dir ab.

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

B. Gemeinsame Einstellungen

Angenommen, Sie möchten den Benutzernamen speichern. So wird es nun zwei Dinge sein, einen Schlüssel Benutzernamen, Wert Wert.

Wie zu speichern

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

Mit putString (), putBoolean (), putInt (), putFloat () und putLong () können Sie den 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 Objektserlisierung wird verwendet, wenn ein Objektstatus gespeichert werden soll, um ihn über ein Netzwerk zu senden, oder wenn Sie ihn auch für Ihren Zweck verwenden können.

Verwenden Sie Java-Beans 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 die Objektserialisierung, um dieses Objekt zu serialisieren und in Ihrer anderen Klasse dieses Objekt zu deserialisieren.

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. Das heißt, 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, lesen Sie:

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. Daten durch Absichten weitergeben

Informationen zum Übergeben von Daten finden Sie im Tutorial Android - Paketdaten zum Übergeben zwischen Aktivitäten mithilfe von Paketklassen .


22

Erstellen Sie Ihre eigene Klasse Customerwie folgt:

import import java.io.Serializable;
public class Customer implements Serializable
{
    private String name;
    private String city;

    public Customer()
    {

    }
    public Customer(String name, String city)
    {
        this.name= name;
        this.city=city;
    }
    public String getName() 
    {
        return name;
    }
    public void setName(String name) 
    {
        this.name = name;
    }
    public String getCity() 
    {
        return city;
    }
    public void setCity(String city) 
    {
        this.city= city;
    }

}

In Ihrer onCreate()Methode

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

    Customer cust=new Customer();
    cust.setName("abc");
    cust.setCity("xyz");

    Intent intent=new Intent(abc.this,xyz.class);
    intent.putExtra("bundle",cust);
    startActivity(intent); 
}

In der xyz activityKlasse müssen Sie den folgenden Code verwenden:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());

..Überprüfen Sie Ihren Code, den Sie "Bundle" als Schlüssel für put cust obj übergeben und von "class" erhalten ..pls verwenden einen Schlüssel entweder "class" oder "bundle" ..
AK Joshi

Ich sehe Fehler: Paket hat IOException beim Schreiben eines serialisierbaren Objekts festgestellt
Arul Mani

15

Der beste Weg ist, eine Klasse (nennen Sie es Control) in Ihrer Anwendung zu haben, die eine statische Variable vom Typ 'Customer' enthält (in Ihrem Fall). Initialisieren Sie die Variable in Ihrer Aktivität A.

Zum Beispiel:

Control.Customer = CustomerClass;

Gehen Sie dann zu Aktivität B und rufen Sie sie aus der Kontrollklasse ab. Vergessen Sie nicht, nach Verwendung der Variablen eine Null zuzuweisen, da sonst Speicherplatz verschwendet wird.


4
@aez Weil es vom Design her schlampig ist und schrecklich kaputt geht, wenn sich die Absicht jemals in einem anderen Prozess befindet.

7
Beim Fortsetzen Ihrer App zu Aktivität B treten Probleme auf. Da die Aktivität von Android beendet werden kann und das Objekt nicht gespeichert wird.
Ryan R

15
public class MyClass implements Serializable{
    Here is your instance variable
}

Jetzt möchten Sie das Objekt dieser Klasse in startActivity übergeben. Verwenden Sie einfach dies:

Bundle b = new Bundle();
b.putSerializable("name", myClassObject);
intent.putExtras(b);

Dies funktioniert hier, weil MyClass implementiert Serializable.



HomeworkData homeworkData = homeWorksList.get (Position); Intent intent = new Intent (c, HomeWorkActivitydetail.class); Bundle b = neues Bundle (); b.putSerializable ("CompleteData", homeworkData); intent.putExtras (b); c.startActivity (Absicht); Zu einem Zeitpunkt des Hinzufügens eines Objekts gibt es einen Fehler beim Hinzufügen von
Objektelementen. Können

Innerhalb der HausaufgabenDaten habe ich einige Werte, die diese hinzufügen sollen
Amitsharma

12

Wenn Sie die von Samuh beschriebene Verwendung wählen, denken Sie daran, dass nur primitive Werte gesendet werden können. Das heißt, Werte, die parcable sind. Wenn Ihr Objekt komplexe Objekte enthält, folgen diese nicht. Zum Beispiel Variablen wie Bitmap, HashMap usw. Diese sind schwierig zu übergeben.

Im Allgemeinen würde ich Ihnen raten nur primitive Datentypen als Statisten zu senden, wie String, int, boolean usw. In Ihrem Fall wäre es: String fname, String lname, int age, und String address.

Meine Meinung: Komplexere Objekte werden durch die Implementierung eines ContentProviders , einer SDCard usw. besser gemeinsam genutzt . Es ist auch möglich, eine statische Variable zu verwenden , dies kann jedoch schnell zu fehleranfälligem Code führen ...

Aber auch hier ist es nur meine subjektive Meinung.


8

Ich verwende Parcelable, um Daten von einer Aktivität zu einer anderen Aktivität zu senden. Hier ist mein Code, der in meinem Projekt gut funktioniert.

public class Channel implements Serializable, Parcelable {

    /**  */
    private static final long serialVersionUID = 4861597073026532544L;

    private String cid;
    private String uniqueID;
    private String name;
    private String logo;
    private String thumb;


    /**
     * @return The cid
     */
    public String getCid() {
        return cid;
    }

    /**
     * @param cid
     *     The cid to set
     */
    public void setCid(String cid) {
        this.cid = cid;
    }

    /**
     * @return The uniqueID
     */
    public String getUniqueID() {
        return uniqueID;
    }

    /**
     * @param uniqueID
     *     The uniqueID to set
     */
    public void setUniqueID(String uniqueID) {
        this.uniqueID = uniqueID;
    }

    /**
     * @return The name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            The name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the logo
     */
    public String getLogo() {
        return logo;
    }

    /**
     * @param logo
     *     The logo to set
     */
    public void setLogo(String logo) {
        this.logo = logo;
    }

    /**
     * @return the thumb
     */
    public String getThumb() {
        return thumb;
    }

    /**
     * @param thumb
     *     The thumb to set
     */
    public void setThumb(String thumb) {
        this.thumb = thumb;
    }


    public Channel(Parcel in) {
        super();
        readFromParcel(in);
    }

    public static final Parcelable.Creator<Channel> CREATOR = new Parcelable.Creator<Channel>() {
        public Channel createFromParcel(Parcel in) {
            return new Channel(in);
        }

        public Channel[] newArray(int size) {

            return new Channel[size];
        }
    };

    public void readFromParcel(Parcel in) {
        String[] result = new String[5];
        in.readStringArray(result);

        this.cid = result[0];
        this.uniqueID = result[1];
        this.name = result[2];
        this.logo = result[3];
        this.thumb = result[4];
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {

        dest.writeStringArray(new String[] { this.cid, this.uniqueID,
                this.name, this.logo, this.thumb});
    }
}

In AktivitätA verwenden Sie es wie folgt:

Bundle bundle = new Bundle();
bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);

Verwenden Sie es in ActivityB folgendermaßen, um Daten abzurufen:

Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");

7

Sie können versuchen, diese Klasse zu verwenden. Die Einschränkung besteht darin, dass es nicht außerhalb eines Prozesses verwendet werden kann.

Eine Aktivität:

 final Object obj1 = new Object();
 final Intent in = new Intent();
 in.putExtra(EXTRA_TEST, new Sharable(obj1));

Andere Aktivität:

final Sharable s = in.getExtras().getParcelable(EXTRA_TEST);
final Object obj2 = s.obj();

public final class Sharable implements Parcelable {

    private Object mObject;

    public static final Parcelable.Creator < Sharable > CREATOR = new Parcelable.Creator < Sharable > () {
        public Sharable createFromParcel(Parcel in ) {
            return new Sharable( in );
        }


        @Override
        public Sharable[] newArray(int size) {
            return new Sharable[size];
        }
    };

    public Sharable(final Object obj) {
        mObject = obj;
    }

    public Sharable(Parcel in ) {
        readFromParcel( in );
    }

    Object obj() {
        return mObject;
    }


    @Override
    public int describeContents() {
        return 0;
    }


    @Override
    public void writeToParcel(final Parcel out, int flags) {
        final long val = SystemClock.elapsedRealtime();
        out.writeLong(val);
        put(val, mObject);
    }

    private void readFromParcel(final Parcel in ) {
        final long val = in .readLong();
        mObject = get(val);
    }

    /////

    private static final HashMap < Long, Object > sSharableMap = new HashMap < Long, Object > (3);

    synchronized private static void put(long key, final Object obj) {
        sSharableMap.put(key, obj);
    }

    synchronized private static Object get(long key) {
        return sSharableMap.remove(key);
    }
}

6

Starten Sie eine andere Aktivität von dieser Aktivität aus und übergeben Sie die Parameter über das Bundle-Objekt

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

Daten zu einer anderen Aktivität abrufen (YourActivity)

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

Dies ist für einfache Datentypen in Ordnung. Aber wenn Sie komplexe Daten zwischen den Aktivitäten übergeben möchten. Sie müssen es 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);

TypeToken <> ist veraltet. Was ist die Alternative?
Ragavendra M

6

Diese Frage wird auch in einer anderen Frage zum Stapelüberlauf behandelt. Bitte schauen Sie sich eine Lösung an, um Daten mithilfe von Serializable absichtlich weiterzugeben . Der Hauptpunkt ist die Verwendung eines BundleObjekts, in dem die erforderlichen Daten gespeichert sind Intent.

 Bundle bundle = new Bundle();

 bundle.putSerializable(key1, value1);
 bundle.putSerializable(key2, value2);
 bundle.putSerializable(key3, value3);

 intent.putExtras(bundle);

So extrahieren Sie Werte:

 Bundle bundle = new Bundle();

 for (String key : bundle.keySet()) {
 value = bundle.getSerializable(key));
 }

Vorteil Serializableist seine Einfachheit. Sie sollten jedoch die Verwendung der ParcelableMethode in Betracht ziehen, wenn Sie viele Daten übertragen möchten, da diese Parcelablespeziell für Android entwickelt wurden und effizienter sind als Serializable. Sie können eine ParcelableKlasse erstellen mit:

  1. ein Online-Tool - Paketierer
  2. ein Plugin für Android Studio - Android Parcelable Code Generator

5

Kreta eine Klasse wie Bean-Klasse und implementieren Sie die SerializableSchnittstelle. Dann können wir es durch die intentMethode führen, zum Beispiel:

intent.putExtra("class", BeanClass);

Dann holen Sie es sich von der anderen Aktivität, zum Beispiel:

BeanClass cb = intent.getSerializableExtra("class");

5

Erstellen Sie zwei Methoden in Ihrer benutzerdefinierten Klasse wie folgt

public class Qabir {

    private int age;
    private String name;

    Qabir(){
    }

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

    // method for sending object
    public String toJSON(){
        return "{age:" + age + ",name:\"" +name +"\"}";
    }

    // method for get back original object
    public void initilizeWithJSONString(String jsonString){

        JSONObject json;        
        try {
            json =new JSONObject(jsonString );
            age=json.getInt("age");
            name=json.getString("name");
        } catch (JSONException e) {
            e.printStackTrace();
        } 
    }
}

Jetzt in Ihrer Absenderaktivität machen Sie das so

Qabir q= new Qabir(22,"KQ");    
Intent in=new Intent(this,SubActivity.class);
in.putExtra("obj", q.toJSON());
startActivity( in);

Und in Ihrer Empfängeraktivität

Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));

3

Ja, die Verwendung eines statischen Objekts ist bei weitem der einfachste Weg, dies mit benutzerdefinierten nicht serialisierbaren Objekten zu tun.


Ja, ich glaube, ich stimme dir tatsächlich zu. Das Erstellen dieser Objekte staticist die bessere Problemumgehung, wenn es einfach unpraktisch ist, weiterhin putExtra()für jede Eigenschaft aufzurufen, die Sie weitergeben möchten. Zum Beispiel möchte ich gerade eine übergeben ArrayList, die Objekte enthält. Ich könnte genauso gut meine ArrayList erstellen static.
Matthew Quiros

3

Android-Aktivitätsobjekte können zerstört und wiederhergestellt werden. Sie müssen also einen anderen Ansatz verwenden, um sie zu betrachten - oder jedes Objekt, das sie erstellen !!! - auf. Das heißt, Sie könnten als statische Klassenreferenz übergeben, aber dann ist das Objekthandle (Java nennt diese "Referenzen" wie SmallTalk; sie sind jedoch keine Referenzen im Sinne von C oder Assembly) möglicherweise später ungültig, da ein "Feature" von Android OE ist jede Aktivität kann später vernichtet und wiederhergestellt werden.

Die ursprüngliche Frage lautete "Wie wird ein Objekt in Android von einer Aktivität an eine andere übergeben?", Und niemand hat darauf geantwortet. Natürlich können Sie serialisieren (Serializable, Parcelable, to / from JSON) und eine Kopie der Objektdaten übergeben, und es kann ein neues Objekt mit denselben Daten erstellt werden. Es werden jedoch NICHT die gleichen Referenzen / Handles verwendet. Viele andere haben erwähnt, dass Sie die Referenz in einem statischen Speicher speichern können. Und das wird funktionieren, wenn Android nicht beschließt, Ihre Aktivität zu zerstören.

Um die ursprüngliche Frage wirklich zu lösen, benötigen Sie eine statische Suche. Außerdem aktualisiert jedes Objekt seine Referenz, wenn es neu erstellt wird. Beispielsweise würde sich jede Android-Aktivität erneut auflisten, wenn onCreate aufgerufen wird. Sie können auch sehen, wie einige Personen die Aufgabenliste verwenden, um eine Aktivität nach Namen zu suchen. (Das System zerstört diese Instanz der Aktivität vorübergehend, um Platz zu sparen. getRunningTasks. Die Aufgabenliste ist effektiv eine spezielle Liste der neuesten Objektinstanz jeder Aktivität.)

Als Referenz:

Gestoppt: "Die Aktivität wird durch eine andere Aktivität vollständig verdeckt (die Aktivität befindet sich jetzt im" Hintergrund "). Eine gestoppte Aktivität ist ebenfalls noch aktiv (das Aktivitätsobjekt bleibt im Speicher erhalten , behält alle Status- und Mitgliedsinformationen bei, ist es jedoch nicht an den Fenstermanager angehängt). Es ist jedoch für den Benutzer nicht mehr sichtbar und kann vom System beendet werden, wenn an anderer Stelle Speicher benötigt wird. "

onDestroy "Das System zerstört diese Instanz der Aktivität vorübergehend , um Platz zu sparen."

Der Message Bus ist also eine praktikable Lösung. Es "schlägt" im Grunde. Anstatt zu versuchen, Verweise auf Objekte zu haben; Anschließend erstellen Sie Ihr Design neu, um MessagePassing anstelle von SequentialCode zu verwenden. Exponentiell schwerer zu debuggen; Sie können diese Art von OperatingEnvironment-Verständnis jedoch ignorieren. Tatsächlich wird jeder Zugriff auf die Objektmethode invertiert, sodass der Aufrufer eine Nachricht sendet und das Objekt selbst einen Handler für diese Nachricht definiert. Viel mehr Code, kann ihn aber mit den Android OE-Einschränkungen robust machen.

Wenn Sie nur die Top-Aktivität wünschen (typisch für Android-Apps, da überall "Kontext" benötigt wird), können Sie jede Aktivität einfach als "Top" im statischen globalen Bereich auflisten lassen, wenn ihr onResume aufgerufen wird. Dann kann Ihr AlertDialog oder was auch immer einen Kontext benötigt, ihn einfach von dort abrufen. Es ist auch ein bisschen glücklich, ein globales zu verwenden, aber es kann die Weitergabe eines Kontexts überall auf und ab vereinfachen, und wenn Sie einen MessageBus verwenden, ist ES sowieso global.


Otto hat den Vorteil, dass er es extern in einer einfachen alten Java-App ausführen kann. Also gut für Entwickler und Tests, ohne sich mit Android herumschlagen zu müssen. Otto hat eine große Lernkurve und das meiste, was es löst, ist bereits auf Android-Art (lokale Übertragung usw.) oder in normalen App-Entwicklungsansätzen gelöst (Sie können eine viel einfachere globale Suche schreiben als die globale Suche von Otto, normale Ansätze sind viel zugänglicher für das Vektorisieren / F3 durch Code und für das schrittweise Debuggen).
TimJowers2

2
  1. Ich weiß, dass statische Aufladung schlecht ist, aber es scheint, dass wir gezwungen sind, sie hier zu verwenden. Das Problem bei Parceables / Seriazables besteht darin, dass die beiden Aktivitäten doppelte Instanzen desselben Objekts aufweisen = Verschwendung von Speicher und CPU.

    public class IntentMailBox {
        static Queue<Object> content = new LinkedList<Object>();
    }

Aktivität aufrufen

IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);

Aufgerufene Aktivität (Beachten Sie, dass onCreate () und onResume () mehrmals aufgerufen werden können, wenn das System Aktivitäten zerstört und neu erstellt.)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. Eine andere Möglichkeit besteht darin, ein statisches Feld der Klasse zu deklarieren, die Sie in genau dieser Klasse übergeben möchten. Es wird nur zu diesem Zweck dienen. Vergessen Sie nicht, dass es in onCreate null sein kann, da Ihr App-Paket vom System aus dem Speicher entladen und später neu geladen wurde.

  2. Wenn Sie bedenken, dass Sie den Aktivitätslebenszyklus noch bewältigen müssen, möchten Sie möglicherweise alle Daten direkt in gemeinsame Einstellungen schreiben, was bei komplexen Datenstrukturen schmerzhaft ist.


1

Die obigen Antworten sind fast alle korrekt, aber für diejenigen, die diese Antworten nicht verstehen, hat Android eine leistungsstarke Absicht. Mithilfe dieser Antworten teilen Sie Daten nicht nur zwischen Aktivitäten, sondern auch mit anderen Komponenten von Android (Broadcasr-Empfänger, Dienste für Inhalte, sofern wir die ContetnResolver-Klasse no Intent verwenden ). In Ihrer Aktivität bauen Sie Absichten auf

Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);

In Ihrer Empfangsaktivität haben Sie

public class SomeActivity extends AppCompactActivity {

    public void onCreate(...){
    ...
          SomeObject someObject = getIntent().getExtras().getParceable("key");
    }

}

Sie müssen die Schnittstelle Parceable oder Serializable auf Ihrem Objekt implementieren, um sie zwischen Aktivitäten gemeinsam nutzen zu können. Es ist schwierig, Parcealbe anstelle der serialisierbaren Schnittstelle auf einem Objekt zu implementieren. Deshalb hat Android speziell dafür ein Plugin. Laden Sie es herunter und verwenden Sie es


0

Ich hatte mich immer gefragt, warum dies nicht so einfach sein kann, wie eine Methode der anderen Aktivität aufzurufen. Ich habe kürzlich eine Utility-Bibliothek geschrieben, die es fast so einfach macht. Sie können es hier überprüfen ( https://github.com/noxiouswinter/gnlib_android/wiki/gnlauncher ).

GNLauncher macht das Senden von Objekten / Daten an eine Aktivität von einer anderen Aktivität usw. so einfach wie das Aufrufen einer Funktion in der Aktivität mit den erforderlichen Daten als Parametern. Es führt die Typensicherheit ein und beseitigt alle Probleme beim Serialisieren, beim Anhängen an die Absicht mithilfe von Zeichenfolgenschlüsseln und beim Rückgängigmachen derselben am anderen Ende.

Verwendungszweck

Definieren Sie eine Schnittstelle mit den Methoden, die Sie für die zu startende Aktivität aufrufen möchten.

public interface IPayload {
    public void sayHello(String name, int age);
}

Implementieren Sie die obige Schnittstelle in der Aktivität, in die gestartet werden soll. Benachrichtigen Sie GNLauncher auch, wenn die Aktivität fertig ist.

public class Activity_1 extends Activity implements IPayload {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Notify GNLauncher when the Activity is ready. 
        GNLauncher.get().ping(this);
    }

    @Override
    public void sayHello(String name, int age) {
        Log.d("gnlib_test", "Hello " + name + "! \nYour age is: " + age);
    }
}

Holen Sie sich in der anderen Aktivität einen Proxy für die obige Aktivität und rufen Sie eine beliebige Methode mit den gewünschten Parametern auf.

public class Activity_2 extends Activity {
    public void onClick(View v) {
        ((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
    }
}

Die erste Aktivität wird gestartet und die Methode mit den erforderlichen Parametern aufgerufen.

Voraussetzungen

Informationen zum Hinzufügen der Abhängigkeiten finden Sie unter https://github.com/noxiouswinter/gnlib_android/wiki#prerequisites .


0

Übergeben Sie das Objekt von einer Aktivität an eine andere Aktivität.

(1) Quellenaktivität

Intent ii = new Intent(examreport_select.this,
                    BarChartActivity.class);

            ii.putExtra("IntentExamResultDetail",
                    (Serializable) your List<ArraList<String>> object here);
            startActivity(ii);

(2) Zielaktivität

List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
            .getSerializableExtra("IntentExamResultDetail");

0

Früher habe ich ein Objekt mit Pacelable oder Serializable zum Übertragen festgelegt, aber wenn ich dem Objekt (Modell) andere Variablen hinzufüge, muss ich alles registrieren. Es ist so unbequem.

Es ist super einfach, Objekte zwischen Aktivitäten oder Fragmenten zu übertragen.

Android DataCache


0

Wir können das Objekt von einer Aktivität zu einer anderen Aktivität übergeben:

SupplierDetails poSuppliersDetails = new SupplierDetails();

Im Inneren haben poSuppliersDetailswir einige Werte. Jetzt sende ich dieses Objekt an die Zielaktivität:

Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);

So erhalten Sie dies in ACtivityTwo:

private SupplierDetails supplierDetails;
    supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");

0

Übergeben Sie eine Aktivität an eine andere:

startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));

Werte abrufen:

String myvalue= getIntent().getExtras("passingkey");

-1

Hallo, ich sehe viele gute Optionen, aber ich habe mich gefragt, warum die Bindung nicht verwendet wurde.

Das Übergeben eines Verweises auf ein Objekt scheint mir nur effizienter zu sein als das Serialisieren und Desterilisieren von Objekten, aber ich habe nicht tief getaucht, um zu sehen, ob dies hinter den Kulissen geschieht.

Das Erstellen eines Ordners ist einfach genug ...

public class MyBinder extends Binder {

    private Object myObject;

    public MyBinder(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

}

Und das Paket zu erstellen, um es zu verwenden, ist kein so schlechter Äther.

public class MyParcelable implements Parcelable {

    private Object myObject;

    public MyParcelable() {
    }

    public MyParcelable(Parcel parcel) {
        myObject = ((MyBinder)parcel.readStrongBinder()).getObject();
    }

    public void setObject(Object object) {
        myObject = object;
    }

    public Object getObject() {
        return myObject;
    }

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeStrongBinder(new MyBinder(myObject));
    }

    public int describeContents() {
        return myObject == null ? 0 : 1;
    }

    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {

        public MyParcelable createFromParcel(Parcel parcel) {
            return new MyParcelable(parcel);
        }

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

    };
}

Diese Logik ist wirklich cool, weil Sie tatsächlich eine Referenz von Aktivität zu Aktivität übergeben.

Ich würde empfehlen, nach Nullen zu suchen und ob die Instanz von Binder MyBinder ist!

und um dies umzusetzen, müssen Sie nur ...

Schicken Sie es ab

Object myObject = "some object";
MyParcelable myParcelable = new MyParcelable();
myParcelable.setObject(myObject);

intent.putExtra("MyParcelable", myParcelable);

Hol es dir zurück

myParcelable = (MyParcelable) getIntent().getExtras().getParcelable("MyParcelable");
myObject = myParcelable.getObject();

Verdammt, jemand könnte verrückt werden und diesen Trottel zu einem echten Generikum machen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.