web-dev-qa-db-fra.com

Comment envoyer des objets par bundle

Je dois transmettre une référence à la classe qui effectue la majorité de mon traitement par le biais d'un bundle.

Le problème est que cela n'a rien à voir avec des intentions ou des contextes et a une grande quantité d'objets non primitifs. Comment conditionner la classe dans un paquetable/serializable et le passer à un startActivityForResult?

114
ahodder

Pour déterminer quelle voie emprunter, il faut répondre non seulement à la question clé de "Pourquoi" de CommonsWare, mais également à celle de "à quoi?" vous le passez.

La réalité est que la seule chose qui peut passer par les ensembles est constituée de données simples - tout le reste est basé sur des interprétations de ce que ces données signifient ou indiquent. Vous ne pouvez pas littéralement passer un objet, mais ce que vous pouvez faire est l’une des trois choses suivantes:

1) Vous pouvez décomposer l’objet en ses données constitutives, et si ce qui se trouve de l’autre bout a connaissance du même type d’objet, il peut assembler un clone à partir des données sérialisées. C'est ainsi que la plupart des types courants passent par les bundles.

2) Vous pouvez passer une poignée opaque. Si vous le transmettez dans le même contexte (bien que l'on puisse se demander pourquoi on dérange), ce sera un descripteur que vous pouvez invoquer ou déréférencer. Mais si vous le transmettez via Binder à un contexte différent, sa valeur littérale sera un nombre arbitraire (en fait, ces nombres arbitraires sont comptés séquentiellement à partir du démarrage). Vous ne pouvez rien faire d'autre que le garder en mémoire jusqu'à ce que vous le renvoyiez au contexte d'origine, ce qui obligera Binder à le reconvertir dans le descripteur d'origine, le rendant ainsi utile à nouveau.

3) Vous pouvez transmettre un descripteur magique, tel qu'un descripteur de fichier ou une référence à certains objets os/platform, et si vous définissez les indicateurs corrects, Binder créera un clone pointant sur la même ressource pour le destinataire. l'autre extrémité. Mais cela ne fonctionne que pour très peu de types d'objets.

Très probablement, vous passez votre classe simplement pour que l’autre extrémité puisse la suivre et vous la rende plus tard, ou vous la transmettez à un contexte dans lequel un clone peut être créé à partir de données constituantes sérialisées ... ou bien vous essayez de faire quelque chose qui ne va tout simplement pas au travail et vous devez repenser toute l'approche.

55
Chris Stratton

Vous pouvez également utiliser Gson pour convertir un objet en JSONObject et le transmettre à un bundle. Pour moi, c’était la façon la plus élégante de le faire. Je n'ai pas testé la façon dont cela affecte les performances.

En activité initiale

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

Dans l'activité suivante

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
151
Laranjeiro

L’interface Parcelable est un bon moyen de transmettre un objet avec une intention.

Comment puis-je rendre mes objets personnalisés Parcelable? est une très bonne réponse sur la façon d'utiliser Parcelable

Le fonctionnaire google docs inclut également un exemple

19
chris

Vous pouvez utiliser l'état global application .

Mise à jour:

Personnalisez puis ajoutez ceci à votre AndroidManifest.xml:

<application Android:label="@string/app_name" Android:debuggable="true" Android:name=".CustomApplication"

Et puis avoir une classe dans votre projet comme ceci:

package com.example;

import Android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

Et parce que " On peut y accéder via getApplication () à partir de n'importe quelle activité ou service ", vous l'utilisez comme ceci:

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

J'espère que ça t'as aidé.

14
Neil

Vous pouvez également créer vos objets Serializable et utiliser les méthodes getSerializable et putSerializable de Bundle.

11
dhaag23

Solution possible:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

Classe CustomObject:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}

Objets sous-personnalisés:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }
10
PraKhar

Une autre façon d’envoyer des objets par bundle est d’utiliser bundle.putByteArray
Exemple de code

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

mettre Object of DataBean dans Bundle:

class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
            Bundle dataBundle=new Bundle();
            DataBean dataObj=new DataBean();
            dataObj.setDate();
            try {
                dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }

            dataIntent.putExtras(dataBundle);

            startActivity(dataIntent);
}

Conversion d'objets en tableaux d'octets

/**
 * Converting objects to byte arrays
 */
static public byte[] object2Bytes( Object o ) throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream( baos );
      oos.writeObject( o );
      return baos.toByteArray();
    }

Récupérer un objet du paquet:

class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//Get Info from Bundle...
    Bundle infoBundle=getIntent().getExtras();
    try {
        dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Méthode pour obtenir des objets à partir de tableaux d'octets:

/**
 * Converting byte arrays to objects
 */
static public Object bytes2Object( byte raw[] )
        throws IOException, ClassNotFoundException {
      ByteArrayInputStream bais = new ByteArrayInputStream( raw );
      ObjectInputStream ois = new ObjectInputStream( bais );
      Object o = ois.readObject();
      return o;
    }

J'espère que cela aidera d'autres amis.

7
Rupesh Yadav

1.Un exemple très direct et facile à utiliser, pour que l'objet à transmettre soit implémenté Serializable.

class Object implements Serializable{
    String firstName;
   String lastName;
}

Objet 2.pass dans le paquet

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
  1. get object from bundle en tant que Serializable puis converti en Object.

    Objet objet = (Objet) getArguments (). GetSerializable ("objet");

1
king_T

Je suis tombé sur cette question lorsque je cherchais un moyen de passer un objet Date. Dans mon cas, comme suggéré dans les réponses, j’ai utilisé Bundle.putSerializable () mais cela ne fonctionnerait pas pour une chose complexe comme le DataManager décrit dans le message original.

Ma suggestion qui donnera un résultat très similaire à celui de placer DataManager dans l’application ou d’en faire un singleton est d’utiliser Dependency Injection et de lier DataManager à une portée Singleton et d’injecter le DataManager chaque fois que cela est nécessaire. Non seulement vous bénéficiez d'une testabilité accrue, mais vous obtiendrez également un code plus propre sans toute la code de la plaque de la chaudière "code de dépendances entre classes et activités". (Robo) Guice est très facile à utiliser et le nouveau cadre Dagger semble également prometteur.

0
britzl

un autre moyen simple de passer un objet à l’aide d’un paquet:

  • dans l'objet de classe, créez une liste statique ou une autre structure de données avec une clé
  • lorsque vous créez l'objet, placez-le dans la structure liste/données avec la clé (par exemple, l'horodatage long lors de la création de l'objet)
  • crée la méthode statique getObject (clé longue) pour extraire l'objet de la liste
  • dans la liasse, passez la clé pour que vous puissiez obtenir l’objet ultérieurement à partir d’un autre point du code
0
shaolin