2012-07-10 1 views
1

J'utilise le code suivant pour enregistrer et récupérer des objets dans et depuis la mémoire interne d'Androids. Je l'ai testé avec un objet chaîne avec succès. Lorsque j'essaie de sauvegarder un bitmap, j'obtiens une exception IOException. (J'ai découvert que je devais appeler la méthode de compression) Donc je remarque que je peux sauver quelques objets, quelles sont les restrictions à la sauvegarde des objets?Certains objets ne sont pas sauvegardés dans la mémoire interne d'Android

Lorsque je sauvegarde un objet, sauvegarde-t-il uniquement les champs? Puis-je sauvegarder des objets contenant d'autres objets? S'il vous plaît, nettoyez-moi.

code:

public Object readObjectFromMemory(String filename) { 
     Object defautObject = null; 
     FileInputStream fis; 
     try { 
      fis = game.openFileInput(filename); 
      ObjectInputStream is = new ObjectInputStream(fis); 
      defautObject = is.readObject(); 
      is.close(); 
      this.gameEngineLog.d(classTAG, "Object successfully read: " + filename); 
     } 
     catch (FileNotFoundException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "FileNotFoundException"); 
      this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename); 

     } 
     catch (StreamCorruptedException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "StreamCorruptedException"); 
      this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename); 

     } 
     catch (IOException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "IOException"); 
      this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename); 

     } 
     catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "ClassNotFoundException"); 
      this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename); 

     } 

     return defautObject; 

    } 

public void writeObjectToMemory(String filename, Object object) { 
     FileOutputStream fos; 
     try { 
      fos = game.openFileOutput(filename, Context.MODE_PRIVATE); 
      ObjectOutputStream os = new ObjectOutputStream(fos); 
      os.writeObject(object); 
      os.close(); 
      this.gameEngineLog.d(classTAG, "Object successfully written: " + filename); 
     } 
     catch (FileNotFoundException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename); 

     } 
     catch (IOException e) { 
      e.printStackTrace(); 
      this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename); 

     } 

    } 

Merci à l'avance.

Répondre

1

La restriction est que tous les objets doivent être sérialisables (implémenter l'interface Serializable). Si un membre de données d'objet d'un objet n'est pas sérialisable, il doit être marqué comme transitoire:

private transient SomeClass notSerializable; 

EDIT au sujet sérialisation membres non sérialisables

Cela dépend de ce que vous essayez de sérialiser ce n'est pas sérialisable. Comme il s'agit d'une question étiquetée avec Android, il pourrait s'agir d'un objet Contexte par exemple.

Les contextes ne sont pas sérialisables pour une bonne raison, ils sont liés à un cycle de vie, soit de l'application, soit d'une activité. Son état est volatile et même si vous pouviez le sérialiser et le désérialiser plus tard, son état interne n'aurait aucun sens, car un nouveau contexte a été créé, un nouveau thread ou même un processus différent peut être en cours d'exécution.

Dans le cas de membres de données tels que Contextes, vous devez les déclarer comme transitoires et réattribuer le contexte courant frais et valide à l'objet désérialisé.

Si vous essayez de sérialiser différents types d'objets que d'une part juste représentent des données comme un bouquet de chaînes et/ou des chiffres, mais d'autre part ne sont pas sérialisables, vous avez deux options:

  • Si ce sont vos classes, ajoutez simplement l'interface Serializable pour les
  • ou vous pouvez personnaliser le processus de sérialisation dans votre classe qui a des membres de données non sérialisables

la personnalisation peut se faire en appliquant le moi thodes

private void writeObject(ObjectOutputStream out) throws IOException; 
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 

Ces méthodes sont invoquées lors de la sérialisation/désérialisation de la classe. L'astuce consiste à prendre les données/l'état d'un objet non sérialisable et à conditionner ces données dans un objet sérialisable à la place. Vous pouvez par exemple utiliser n'importe quel objet Collection comme une ArrayList pour stocker séquentiellement les données brutes.

Supposons que vous vouliez sérialiser un objet Location (pour les coordonnées d'emplacement géographique) et supposons également que cet objet n'est pas sérialisable.Mais vous savez qu'il se compose de trois valeurs qui peuvent être sérialisés:

  • à double longitude
  • à double latitude
  • à double altitude
  • (et d'autres comme fournisseur, vitesse, temps ...)

Vous pouvez stocker ces trois valeurs dans une ArrayList ou vous pouvez créer votre propre classe sérialisable personnalisée qui stocke ces valeurs à des fins de sérialisation. Placez ArrayList ou votre objet intermédiaire sérialisable dans ObjectOutputStream de votre méthode writeObject personnalisée.

Dans readObject, vous devez inverser ces étapes et reconstruire votre membre de données qui n'est pas sérialisable en fonction des données brutes que vous avez sérialisées.

Je suggère également la lecture documentation about serialization

+0

Lorsque je charge l'objet, les objets marqués comme transitoires sont-ils définis sur null? –

+0

Oui, car il n'y a pas d'autre moyen d'exprimer un état indéfini en Java. – tiguchi

+0

Est-il possible d'enregistrer des types de données transitoires? –

0

Oui, Sun vous pouvez enregistrer tous les types de données dans un objet, il vous suffit de vous assurer que vous définissez toutes les variables à l'intérieur de votre objet:

public class YourObject{ 
int yourInteger; 
String yourString; 
Bitmap yourBitmap; 
float yourFloat; 
... 
} 

vous devez également vous assurer que vous définissez les champs au large de ces objets à l'aide d'une méthode set:

public class YourObject{ 
int yourInteger; 
String yourString; 
Bitmap yourBitmap; 
float yourFloat; 
... 
//sets the value of yourInt 
public void setYourInteger(int yourInt){ 
this.yourInt = yourInt; 

}

} 

Si vous ne définissez pas explicitement les champs, vous ne pourrez pas les enregistrer.

+0

Donc, je peux enregistrer un objet qui contient un objet bitmap, mais je ne peux pas enregistrer un objet bitmap par lui-même (avec le code que j'ai fourni ci-dessus)? –

+0

Pouvez-vous fournir le code de votre classe d'objets, ainsi que le code que vous utilisez pour appeler la méthode 'writeObject'? – BlackHatSamurai

0

De la Javadoc Oracle:

Un ObjectOutputStream écrit les deux types de données primitives et graphiques de objets Java à un OutputStream sous-jacent. Les objets et autres données peuvent ensuite être lus (reconstitués) à l'aide d'un ObjectInputStream. Le stockage persistant d'objets peut être accompli en utilisant un fichier pour le flux. Si le flux est un flux de socket réseau, les objets peuvent être reconstitués sur un autre hôte ou dans un autre processus.

Seuls les objets qui prennent en charge l'interface java.io.Serializable ou java.io.Externalizable peuvent être sérialisés à un flux de sortie . La classe de chaque objet sérialisable est codée, y compris le nom de classe et la signature de la classe, les valeurs des champs et tableaux non statiques et non-transitoires de l'objet, y compris tous les objets référencés par l'objet (à l'exception de ceux ne pas implémenter l'interface java.io.Serializable eux-mêmes). Plusieurs références au même objet sont codées à l'aide d'un mécanisme de partage de référence , de sorte qu'un graphique de l'objet peut être restauré de façon appropriée .

Le mécanisme de sérialisation par défaut d'un objet écrit la classe l'objet, la signature de classe et les valeurs de tous les champs non statiques non-transitoires. Les références à d'autres objets (sauf dans les champs transitoires ou statiques ) provoquent également l'écriture de ces objets.

Questions connexes