web-dev-qa-db-fra.com

Comment passer un objet d'une activité à une autre sur Android

J'essaie de travailler à l'envoi d'un objet de mon client classe d'une variable Activity et de l'afficher dans une autre variable Activity.

Le code de la classe de client:

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

Je veux envoyer son objet d'un Activity à un autre, puis afficher les données sur l'autre Activity.

Comment puis-je y arriver?

662
kaibuki

Une option pourrait être de laisser votre classe personnalisée implémenter l'interface Serializable, puis vous pouvez passer des instances d'objet dans l'objet supplémentaire à l'aide de la variante putExtra(Serializable..) de la méthode Intent#putExtra().

Pseudocode :

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

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

Remarque: Assurez-vous que chaque classe imbriquée de votre classe personnalisée principale a implémenté l'interface Serializable pour éviter toute exception de sérialisation. Par exemple: 

class MainClass implements Serializable {

    public MainClass() {}

    public static class ChildClass implements Serializable {

        public ChildClass() {}
    }
}
780
Samuh

Implémentez votre classe avec Serializable. Supposons qu'il s'agit de votre classe d'entité:

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

Nous envoyons l'objet appelé dene de l'activité X à l'activité Y. Quelque part dans l'activité X;

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

Dans l'activité Y, nous obtenons l'objet.

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

C'est tout.

278
Mustafa Güven
  • L'utilisation globale de les variables statiques n'est pas un bon logiciel d'ingénierie} pratique. 
  • Conversion des champs d'un objet en primitive les types de données peuvent être un travail mouvementé
  • Utiliser sérialiser est OK, mais ce n'est pas performant sur la plate-forme Android. 
  • Parcelable est spécifiquement conçu pour Android et vous devriez l'utiliser. Voici un exemple simple: Passage d'objets personnalisés entre des activités Android

Vous pouvez générer du code parcellaire pour votre classe en utilisant ce site .

109
SohailAziz

En appelant une activité 

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

Dans ToClass.Java, recevez l'activité de 

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

Assurez-vous que la classe de clients implémente de manière fragmentable

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

D'après mon expérience, il existe trois solutions principales, chacune avec leurs inconvénients et leurs avantages:

  1. Mise en oeuvre de Parcelable

  2. Implémentation de Serializable

  3. Utilisation d'une bibliothèque de bus d'événements légère (par exemple, EventBus de Greenrobot ou Otto de Square)

Parcelable - standard rapide et Android, mais il contient beaucoup de code passe-partout et nécessite des chaînes codées en dur comme référence lors de l'extraction de valeurs (non fortement typées).

Sérialisable - proche de zéro, mais c'est l'approche la plus lente et nécessite également des chaînes codées de manière irréversible pour extraire les valeurs de l'intention (non fortement typées).

Event Bus - zéro passe-partout, approche la plus rapide et ne nécessite pas de chaînes codées en dur, mais nécessite une dépendance supplémentaire (bien que généralement léger, ~ 40 Ko)

J'ai publié une comparaison très détaillée autour de ces trois approches, y compris des critères d'efficacité.

79
Steven Mark Ford

Utilisez gson pour convertir votre objet en JSON et le transmettre par intention. Dans la nouvelle activité, convertissez le JSON en objet.

Dans votre build.gradle, ajoutez ceci à vos dépendances

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

Dans votre activité, convertissez l'objet en json-string:

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

Dans votre activité de réception, reconvertissez la chaîne json en objet d'origine:

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

Pour Kotlin c'est à peu près pareil

Transmettre les données

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

Recevoir les données

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

Vous pouvez également écrire les données de l'objet dans des chaînes et des entêtes temporaires et les transmettre à l'activité. Bien sûr, de cette façon, vous obtenez les données transportées, mais pas l'objet lui-même.

Mais si vous voulez simplement les afficher et ne pas utiliser l'objet dans une autre méthode ou quelque chose comme ça, ça devrait être suffisant. Je l'ai fait de la même manière pour simplement afficher les données d'un objet dans une autre activité.

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

Vous pouvez aussi les transmettre directement au lieu des noms temporaires, mais de cette façon, c'est plus clair, à mon avis. De plus, vous pouvez définir les ivars temporaires sur null pour qu'ils soient nettoyés plus tôt par GarbageCollector.

Bonne chance!

Remarque: remplacez toString () au lieu d’écrire votre propre méthode d’impression.

Comme mentionné dans les commentaires ci-dessous, voici comment récupérer vos données dans une autre activité:

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

J'ai trouvé une méthode simple et élégante:

  • PAS de colis
  • NO Serializable
  • NO champ statique
  • Pas de bus événementiel

Méthode 1

Code pour la première activité:

    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 pour la deuxième activité:

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

vous constaterez que objSent & objReceived ont le même hashCode, ils sont donc identiques.

Mais pourquoi pouvons-nous passer un objet Java de cette façon?

En fait, le classeur Android créera une référence JNI globale pour un objet Java et publiera cette référence JNI globale en l'absence de référence pour cet objet Java. binder sauvegardera cette référence JNI globale dans l'objet Binder.

* ATTENTION: cette méthode ne fonctionne UNIQUEMENT que si les deux activités sont exécutées dans le même processus. Sinon, jetez ClassCastException dans (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") *

classe ObjectWrapperForBinder defination

public class ObjectWrapperForBinder extends Binder {

    private final Object mData;

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

    public Object getData() {
        return mData;
    }
}

Méthode 2

  • pour l'expéditeur,
    1. utilisez une méthode native personnalisée pour ajouter votre objet Java à la table de référence globale JNI (via JNIEnv :: NewGlobalRef)
    2. mettez le nombre entier de retour (en fait, JNIEnv :: NewGlobalRef renvoie le jobject, qui est un pointeur, nous pouvons le convertir en int en toute sécurité) à votre intention (via Intent :: putExtra)
  • pour le récepteur
    1. obtenir un entier de Intent (via Intent :: getInt) 
    2. utilisez une méthode native personnalisée pour restaurer votre objet Java à partir de la table de référence globale JNI (via JNIEnv :: NewLocalRef)
    3. supprimer un élément de la table de référence globale JNI (via JNIEnv :: DeleteGlobalRef),

Mais la méthode 2 présente un problème mineur mais sérieux: si le destinataire ne parvient pas à restaurer l'objet Java (par exemple, une exception survient avant la restauration de l'objet Java ou si l'activité du destinataire n'existe pas du tout), l'objet Java devient alors une Fuite de mémoire ou d'orphelin, La méthode 1 n'a pas ce problème, car le classeur Android gérera cette exception

Méthode 3

Pour appeler l'objet Java à distance, nous allons créer un contrat/une interface de données pour décrire l'objet Java, nous utiliserons le fichier aidl

IDataContract.aidl

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

Code pour la première activité

    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 pour la deuxième activité:

changer l'attribut Android: process dans AndroidManifest.xml en un nom de processus non vide pour s'assurer que la deuxième activité s'exécute dans un autre processus

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

De cette manière, nous pouvons passer une interface entre deux activités même si elles s'exécutent dans un processus différent, et appeler la méthode d'interface à distance.

Méthode 4

la méthode 3 ne semble pas assez simple car nous devons implémenter une interface auxiliaire . Si vous souhaitez simplement effectuer une tâche simple et que la valeur renvoyée par la méthode est inutile, vous pouvez utiliser Android.os.Messenger.

Code pour la première activité (expéditeur):

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 pour la deuxième activité (récepteur):

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

    }
}

Tous les Messenger.send s'exécuteront dans un gestionnaire de manière asynchrone et séquentielle.

En fait, Android.os.Messenger est aussi une interface aidl, si vous avez le code source Android, vous pouvez trouver un fichier nommé IMessenger.aidl. 

package Android.os;

import Android.os.Message;

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

J'ai créé une classe d'assistance singleton qui contient des objets temporaires.

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

Au lieu de mettre vos objets dans Intent, utilisez IntentHelper:

IntentHelper.addObjectForKey(obj, "key");

Dans votre nouvelle activité, vous pouvez obtenir l'objet:

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

N'oubliez pas qu'une fois chargé, l'objet est supprimé pour éviter les références inutiles. 

25
Roger Sanoli

Vous pouvez accéder aux variables ou aux objets d’autres classes ou d’Activités de plusieurs façons.

A. Base de données

B. Préférences partagées.

C. Sérialisation d'objet.

D. Une classe pouvant contenir des données communes peut être nommée Utilitaires communs. Cela dépend de toi.

E. Transmission de données via Intents et une interface pouvant être parcellisée.

Cela dépend des besoins de votre projet.

A. Base de données

SQLite est une base de données open source intégrée à Android. SQLite prend en charge les fonctionnalités de base de données relationnelles standard telles que la syntaxe SQL, les transactions et les instructions préparées.

Tutoriels

B. Préférences partagées

Supposons que vous souhaitiez stocker un nom d'utilisateur. Donc, il y aura maintenant deux choses, un nom d'utilisateur key, value.

Comment stocker

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

_ {En utilisant putString (), putBoolean (), putInt (), putFloat () et putLong (), vous pouvez enregistrer votre type d'état souhaité.

Comment chercher

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

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

C. Sérialisation d'objet

La sérialisation d'objet est utilisée si nous voulons enregistrer un état d'objet pour l'envoyer sur un réseau ou si vous pouvez également l'utiliser à vos fins.

Utilisez les haricots Java et stockez-les comme l'un de ses champs et utilisez des accesseurs et des configurateurs pour cela.

JavaBeans sont des classes Java possédant des propriétés. Pensez àproperties en tant que variables d'instance privée. Comme ils sont privés, le seul moyen De les accéder à l'extérieur de leur classe est d'utiliser des méthodes de la classe. Les méthodes qui changent la valeur d'une propriété sont appelées méthodes setter et les méthodes qui récupèrent la valeur d'une propriété sont appelées méthodes getter.

public class VariableStorage implements Serializable  {

    private String inString;

    public String getInString() {
        return inString;
    }

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

Définissez la variable dans votre méthode de messagerie à l'aide de

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

Utilisez ensuite la sérialisation d'objet pour sérialiser cet objet et dans votre autre classe pour la désérialiser.

Lors de la sérialisation, un objet peut être représenté sous la forme d'une séquence d'octets contenant les données de l'objet, ainsi que des informations sur le type de l'objet et les types de données stockés dans l'objet.

Une fois qu'un objet sérialisé a été écrit dans un fichier, il peut être lu à partir du fichier et désérialisé. En d'autres termes, les informations de type et les octets représentant l'objet et ses données peuvent être utilisés pour recréer l'objet en mémoire.

Si vous souhaitez un tutoriel pour cela, reportez-vous à:

D. CommonUtilities

Vous pouvez créer vous-même un cours pouvant contenir des données communes dont vous avez souvent besoin dans votre projet.

Échantillon

public class CommonUtilities {

    public static String className = "CommonUtilities";

}

E. Transmission de données à travers des intentions

Veuillez vous référer au tutoriel Android - Données de parcelle à transmettre entre les activités utilisant des classes Parcelable pour cette option de transmission de données.

23
Nikhil Agrawal

Créez votre propre classe Customer comme suit:

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

}

Dans votre méthode onCreate()

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

Dans la classe xyz activity, vous devez utiliser le code suivant:

Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());
18
Mayur Chudasama
public class MyClass implements Serializable{
    Here is your instance variable
}

Maintenant, vous voulez passer l'objet de cette classe dans startActivity. Utilisez simplement ceci:

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

Cela fonctionne ici car MyClass implémente Serializable.

15
Dhiral Pandya

Le meilleur moyen consiste à avoir une classe (appelez-la Control) dans votre application qui contiendra une variable statique de type 'Client' (dans votre cas). Initialisez la variable dans votre activité A.

Par exemple:

Control.Customer = CustomerClass;

Ensuite, allez à l'activité B et récupérez-le dans la classe Control. N'oubliez pas d'attribuer un null après avoir utilisé la variable, sinon la mémoire sera perdue.

15
Umesh

Si vous choisissez d'utiliser la manière décrite par Samuh, n'oubliez pas que seules les valeurs primitives peuvent être envoyées. C'est-à-dire des valeurs qui sont parcables. Donc, si votre objet contient des objets complexes, ceux-ci ne suivront pas. Par exemple, des variables telles que Bitmap, HashMap, etc., sont difficiles à transmettre par l'intention.

En général, je vous conseillerais d’envoyer uniquement les types de données primitifs, tels que String, int, boolean, etc. Dans votre cas, il s’agirait de: String fname, String lname, int age et String address.

Mon avis: Les objets plus complexes sont mieux partagés en implémentant un ContentProvider , SDCard , etc. Il est également possible d'utiliser une variable statique , mais cela peut rapidement conduire à un code source d'erreurs. ..

Mais encore une fois, c'est juste mon opinion subjective.

12
Vidar Vestnes

J'utilise parcelable pour envoyer des données d'une activité à une autre activité. Voici mon code qui fonctionne bien dans mon projet.

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

En activité, utilisez-le comme ceci:

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

Dans ActivityB, utilisez-le comme ceci pour obtenir des données:

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

Vous pouvez essayer d'utiliser cette classe. La limitation est qu'il ne peut pas être utilisé en dehors d'un processus.

Une activité:

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

Autre activité:

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

Cette question est également abordée dans une autre question relative au dépassement de capacité. S'il vous plaît jeter un oeil à une solution à Passing données à travers l'intention en utilisant Serializable . Le point principal concerne l'utilisation de l'objet Bundle qui stocke les données nécessaires dans Intent.

 Bundle bundle = new Bundle();

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

 intent.putExtras(bundle);

Pour extraire des valeurs:

 Bundle bundle = new Bundle();

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

L’avantage de Serializable est sa simplicité. Cependant, vous devriez envisager d'utiliser la méthode Parcelable si vous avez besoin de transférer beaucoup de données, car Parcelable est spécialement conçu pour Android et est plus efficace que Serializable. Vous pouvez créer la classe Parcelable en utilisant:

  1. un outil en ligne - parcelabler
  2. un plugin pour Android Studio - Générateur de code Android Parcelable 
6
Sa Qada

Créez une classe comme la classe de haricot et implémentez l'interface Serializable. Ensuite, nous pouvons le passer par la méthode intent, par exemple:

intent.putExtra("class", BeanClass);

Ensuite, récupérez-le à partir de l'autre activité, par exemple: 

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

Créez deux méthodes dans votre classe personnalisée comme ceci

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

Maintenant, dans votre activité d'envoi, faites comme ceci

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

Et dans votre récepteur Activité

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

Commencez une autre activité à partir de cette activité et passez les paramètres via l'objet Bundle

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

Récupérer des données sur une autre activité (YourActivity)

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

C'est correct pour un type de données simple . Mais si vous voulez transmettre des données complexes entre les activités. Vous devez d'abord le sérialiser.

Ici nous avons le modèle employé

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

    getters...
    setters...
}

Vous pouvez utiliser Gson lib fourni par Google pour sérialiser les données complexes Comme ceci

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

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

Ouais, utiliser un objet statique est de loin le moyen le plus simple de le faire avec des objets personnalisés non sérialisables.

3
alistair

Les objets d'activité Android peuvent être détruits et reconstitués. Donc, vous devrez utiliser une autre approche pour regarder eux - ou tout objet créé par eux} !!! - up. Autrement dit, vous pouvez passer en tant que référence de classe statique, mais ensuite le descripteur d'objet (Java appelle ces "références", comme le fait Smalltalk; mais ce ne sont pas des références au sens de C ou Assembly) sera éventuellement non valide ultérieurement car une "fonctionnalité" de Android OE est toute activité peut être annihilé et reconstitué plus tard.

La question initiale demandait "Comment passer d'un objet à une autre dans Android" et personne n'a répondu à cette question. Bien sûr, vous pouvez sérialiser (Serializable, Parcelable, to/from JSON) et transmettre une copie des données de l'objet et créer un nouvel objet contenant les mêmes données. mais il n'aura PAS les mêmes références/poignées. En outre, beaucoup d'autres ont mentionné que vous pouvez stocker la référence dans un magasin statique. Et cela fonctionnera à moins que Android ne décide de détruire votre activité. 

Donc, pour vraiment résoudre la question initiale, vous auriez besoin d'une recherche statique et chaque objet mettra à jour sa référence quand/s'il est recréé. Par exemple. chaque activité Android se remettrait en vente si son onCreate était appelé. Vous pouvez également voir comment certaines personnes utilisent la liste des tâches pour rechercher une activité par son nom. (le système est en train de détruire temporairement cette instance de l'activité pour économiser de l'espace .. getRunningTasks, la liste des tâches est en réalité une liste spécialisée de l'instance d'objet la plus récente de chaque activité).

Pour référence:

Arrêté: "L'activité est complètement masquée par une autre activité (l'activité est maintenant dans" l'arrière-plan "). Une activité arrêtée est également toujours active (l'objet l'objet Activity est conservé en mémoire}, il conserve toutes les informations sur l'état et les membres n’est plus visible par l’utilisateur et peut être tué par le système lorsque la mémoire est nécessaire ailleurs. "

onDestroy "Le système est temporairement détruit cette instance de l'activité pour économiser de l'espace."

Ainsi, le bus de messages est une solution viable. C'est fondamentalement "punts". Plutôt que d'essayer d'avoir des références à des objets; Ensuite, vous réarchivez votre conception pour utiliser MessagePassing au lieu de SequentialCode. Exponentiellement plus difficile à déboguer; mais cela vous permet d'ignorer ce genre de compréhension OperatingEnvironment. Effectivement, chaque accès à une méthode d'objet est inversé afin que l'appelant publie un message et que l'objet lui-même définisse un gestionnaire pour ce message. Beaucoup plus de code mais peut le rendre robuste avec les restrictions Android OE.

Si tout ce que vous voulez, c'est l'activité top (ce qui est typique dans les applications Android en raison de la nécessité de "Context" partout dans le monde), vous pouvez simplement demander à chaque activité de se nommer "top" dans l'espace global statique lorsque son onResume est appelé. Ensuite, votre AlertDialog ou ce qui nécessite un contexte peut simplement le récupérer à partir de là. En outre, il est un peu malicieux d’utiliser une approche globale, mais il est possible de simplifier le passage d’un contexte à l’autre et, bien sûr, lorsque vous utilisez un MessageBus, puis l’informatique IS est globale. 

3
TimJowers2
  1. Je sais que statique est mauvais, mais il semble que nous sommes obligés de l'utiliser ici. Le problème avec parceables/seriazables est que les deux activités ont des instances dupliquées du même objet = gaspillage de mémoire et de CPU.

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

Activité d'appel

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

Activité appelée (notez que onCreate () et onResume () peut être appelé plusieurs fois lorsque le système détruit et recrée des activités)

if (IntentMailBox.content.size()>0)
    level = (Level) IntentMailBox.content.poll();
else
    // Here you reload what you have saved in onPause()
  1. Une autre méthode consiste à déclarer un champ statique de la classe que vous voulez transmettre dans cette même classe. Cela ne servira qu'à cette fin. N'oubliez pas qu'il peut être nul dans onCreate, car votre package d'application a été déchargé de la mémoire par le système et rechargé plus tard.

  2. Gardant à l'esprit que vous devez toujours gérer le cycle de vie d'une activité, vous pouvez écrire toutes les données directement dans des préférences partagées, avec des structures de données complexes telles quelles.

2
Anton Duzenko

Passer un objet d'une activité à une autre. 

(1) activité source

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

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

(2) activité de destination

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

Nous pouvons passer l'objet d'une activité à une autre:

SupplierDetails poSuppliersDetails = new SupplierDetails();

Dans poSuppliersDetails nous avons quelques valeurs. Maintenant, j'envoie cet objet pour cibler l'activité:

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

Comment l'obtenir dans ACtivityTwo:

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

Passez d'une activité à une autre:

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

Obtenir des valeurs:

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

J'avais l'habitude de définir l'objet avec Pacelable ou Serializable à transférer, mais chaque fois que j'ajoute d'autres variables à l'objet (modèle), je dois tout enregistrer. C'est tellement peu pratique. 

C'est super facile de transférer un objet entre des activités ou des fragments. 

Android DataCache

0
kimkevin

Je m'étais toujours demandé pourquoi cela ne pouvait pas être aussi simple que d'appeler une méthode de l'autre activité. J'ai récemment écrit une bibliothèque d'utilitaires qui le rend presque aussi simple que cela. Vous pouvez le vérifier ici ( https://github.com/noxiouswinter/gnlib_Android/wiki/gnlauncher ). 

GNLauncher facilite l'envoi d'objets/de données à une activité à partir d'une autre activité, par exemple, il suffit d'appeler une fonction dans l'activité avec les données requises en tant que paramètres. Il introduit la sécurité de type et supprime tous les problèmes liés à la sérialisation, la liaison à l'intention à l'aide de clés de chaîne et l'annulation de celle-ci à l'autre extrémité.

Usage

Définissez une interface avec les méthodes que vous souhaitez appeler dans l'activité à lancer.

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

Implémentez l'interface ci-dessus sur l'activité à lancer dans . Avertissez également GNLauncher lorsque l'activité est prête.

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

Dans l'autre activité, obtenez un proxy pour l'activité ci-dessus et appelez n'importe quelle méthode avec les paramètres souhaités.

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

La première activité sera lancée et la méthode appelée avec les paramètres requis.

Conditions préalables

Veuillez vous référer à https://github.com/noxiouswinter/gnlib_Android/wiki#prerequisites pour plus d'informations sur l'ajout de dépendances. 

0
jinais