J’ai besoin de transmettre une référence à la classe qui effectue la majorité de mon traitement via un bundle.
Le problème est qu’il n’a rien à voir avec les intentions ou les contextes et qu’il contient un grand nombre d’objects non primitifs. Comment compresser la classe en un parcelable / serializable et la passer à un startActivityForResult
?
Déterminer la voie à suivre exige de répondre non seulement à la question clé de CommonsWare, à savoir “pourquoi”, mais aussi à “à quoi?” vous le passez
La réalité est que la seule chose qui peut passer par des ensembles de données est des données simples: tout le rest repose sur des interprétations de ce que ces données signifient ou indique. Vous ne pouvez pas littéralement passer un object, mais vous pouvez faire l’une des trois choses suivantes:
1) Vous pouvez diviser l’object en ses données de base, et si ce qui se trouve à l’autre extrémité connaît le même type d’object, il peut assembler un clone à partir des données sérialisées. C’est ainsi que la plupart des types courants passent par des ensembles.
2) Vous pouvez passer une poignée opaque. Si vous le transmettez dans le même contexte (même si on peut se demander pourquoi cela pose problème), ce sera un handle que vous pouvez invoquer ou déréférencer. Mais si vous le transmettez à Binder dans un contexte différent, sa valeur littérale sera un nombre arbitraire (en fait, ces nombres arbitraires comptent séquentiellement depuis le démarrage). Vous ne pouvez rien faire mais en garder une trace, jusqu’à ce que vous la renvoyiez au contexte d’origine, ce qui obligera Binder à le reconvertir dans le descripteur d’origine, le rendant à nouveau utile.
3) Vous pouvez passer un handle magique, tel qu’un descripteur de fichier ou une référence à certains objects os / platform, et si vous définissez les bons drapeaux, Binder créera un clone pointant vers la même ressource pour le destinataire, qui peut être utilisé sur l’autre extrémité. Mais cela ne fonctionne que pour un très petit nombre d’objects.
Très probablement, vous passez votre classe pour que l’autre extrémité puisse la suivre et vous la redonner plus tard, ou vous la transmettez à un contexte où un clone peut être créé à partir de données constituantes sérialisées … ou bien vous essayez de faire quelque chose qui ne fonctionne tout simplement pas et vous devez repenser toute l’approche.
Vous pouvez également utiliser Gson pour convertir un object en object JSONObject et le transmettre à un ensemble. Pour moi, c’était la manière la plus élégante de le faire. Je n’ai pas testé comment 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
Ssortingng jsonMyObject; Bundle extras = getIntent().getExtras(); if (extras != null) { jsonMyObject = extras.getSsortingng("myObject"); } MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
L’interface Parcelable est un bon moyen de passer un object avec une intention.
Comment puis-je rendre mes objects personnalisés Parcelable? est une très bonne réponse sur la façon d’utiliser Parcelable
Les documents officiels de Google incluent également un exemple
Vous pouvez utiliser l’état d’ application global.
Mettre à jour:
Personnalisez puis ajoutez ceci à votre AndroidManifest.xml:
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 () depuis n'importe quelle activité ou service ", vous l'utilisez comme ceci:
CustomApplication application = (CustomApplication)getApplication(); application.someVariable = 123;
J'espère que cela pourra aider.
Vous pouvez également rendre vos objects Serializable et utiliser les méthodes getSerializable et putSerializable de Bundle .
Une autre façon d’envoyer des objects par bundle consiste à utiliser bundle.putByteArray
Code exemple
public class DataBean implements Serializable { private Date currentTime; public setDate() { currentTime = Calendar.getInstance().getTime(); } public Date getCurrentTime() { return currentTime; } }
mettre Objet de 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’objects 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ère l’object de l’ensemble:
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 objects à 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.
Solution possible:
Bundle bundle = new Bundle(); bundle.putSerializable("key", new CustomObject());
Classe CustomObject:
class CustomObject implements Serializable{ private SubCustomObject1 sc1; private SubCustomObject2 sc2; }
Objets Subcustom:
class SubCustomObject1 implements Serializable{ } class SubCustomObject2 implements Serializable{ }
C’est une réponse très tardive à ma propre question, mais elle continue d’attirer l’attention, alors je pense que je dois y répondre. La plupart de ces réponses sont correctes et traitent parfaitement le travail. Cependant, cela dépend des besoins de l’application. Cette réponse sera utilisée pour décrire deux solutions à ce problème.
Le premier est l’ application , car il a été le plus parlé de réponse ici. L’application est un bon object pour placer des entités nécessitant une référence à un contexte. Un `ServerSocket` aurait sans doute besoin d’un contexte (pour les E / S de fichier ou les mises à jour simples` ListAdapter`). Personnellement, je préfère cette route. J’aime les applications, elles sont utiles pour la récupération de contexte (car elles peuvent être rendues statiques et ne provoquent probablement pas de fuite de mémoire) et ont un cycle de vie simple.
Le service` est deuxième. Un `Service` est en fait le meilleur choix pour mon problème car c’est ce que les services sont conçus pour faire:
Un service est un composant d'application qui peut effectuer des opérations de longue durée dans l'arrière-plan et ne fournit pas d'interface utilisateur.
Les services sont soignés en ce sens qu’ils ont un cycle de vie plus défini, plus facile à contrôler. En outre, si nécessaire, les services peuvent être exécutés à l’extérieur de l’application (par exemple, au démarrage). Cela peut être nécessaire pour certaines applications ou juste une fonctionnalité intéressante.
Ce n’était pas une description complète de l’un ou de l’autre, mais j’ai laissé des liens vers les documents pour ceux qui veulent en savoir plus. Dans l’ensemble, le Service
est le meilleur pour l’instance dont j’avais besoin – exécuter un ServerSocket sur mon périphérique SPP.
Je suis tombé sur cette question quand je cherchais un moyen de passer un object Date. Dans mon cas, comme cela a été suggéré parmi 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 à placer ledit DataManager dans l’application ou à en faire un Singleton consiste à utiliser l’dependency injection et à lier le DataManager à une scope Singleton et à injecter le DataManager partout où cela est nécessaire. Non seulement vous bénéficiez d’une testabilité accrue, mais vous obtenez également un code plus propre sans toute la plaque de la chaudière “dépendant des dépendances entre les classes et les activités”. (Robo) Guice est très facile à utiliser et le nouveau framework Dagger est également prometteur.
un autre moyen simple de passer un object en utilisant un bundle:
1. Un exemple très direct et facile à utiliser, faites passer l’object à implémenter Serializable.
class Object implements Serializable{ Ssortingng firstName; Ssortingng lastName; }
2. Passer l’object en liasse
Bundle bundle = new Bundle(); Object Object = new Object(); bundle.putSerializable("object", object);
Obtient l’object transmis depuis le bundle en tant que Serializable, puis converti en Object.
Object object = (Object) getArguments (). GetSerializable (“object”);