Pourquoi Android propose-t-il 2 interfaces pour sérialiser des objets? Les objets sérialisables interagissent-ils avec les Binder
fichiers Android et AIDL?
Pourquoi Android propose-t-il 2 interfaces pour sérialiser des objets? Les objets sérialisables interagissent-ils avec les Binder
fichiers Android et AIDL?
Réponses:
Dans Android, nous ne pouvons pas simplement transmettre des objets à des activités. Pour ce faire, les objets doivent implémenter Serializable
ou Parcelable
interfacer.
Sérialisable
Serializable
est une interface Java standard. Vous pouvez simplement implémenter l' Serializable
interface et ajouter des méthodes de remplacement. Le problème avec cette approche est que la réflexion est utilisée et c'est un processus lent. Cette méthode crée un grand nombre d'objets temporaires et provoque un certain ramassage des ordures. Cependant, l' Serializable
interface est plus facile à implémenter.
Regardez l'exemple ci-dessous (sérialisable):
// MyObjects Serializable class
import java.io.Serializable;
import java.util.ArrayList;
import java.util.TreeMap;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Serializable {
private String name;
private int age;
public ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyObjects instance via intent
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getSerializableExtra("UniqueKey");
Parcelable
Parcelable
processus est beaucoup plus rapide que Serializable
. L'une des raisons à cela est que nous sommes explicites sur le processus de sérialisation au lieu d'utiliser la réflexion pour l'inférer. Il va également de soi que le code a été fortement optimisé à cet effet.
Regardez l'exemple ci-dessous (Parcelable):
// MyObjects Parcelable class
import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Parcelable {
private int age;
private String name;
private ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
this.name = name;
this.age = age;
this.address = address;
}
public MyObjects(Parcel source) {
age = source.readInt();
name = source.readString();
address = source.createStringArrayList();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeStringList(address);
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public static final Creator<MyObjects> CREATOR = new Creator<MyObjects>() {
@Override
public MyObjects[] newArray(int size) {
return new MyObjects[size];
}
@Override
public MyObjects createFromParcel(Parcel source) {
return new MyObjects(source);
}
};
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");
Vous pouvez passer ArrayList
d'objets Parcelable comme ci-dessous:
// Array of MyObjects
ArrayList<MyObjects> mUsers;
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putParcelableArrayListExtra("UniqueKey", mUsers);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
ArrayList<MyObjects> mUsers = mIntent.getParcelableArrayList("UniqueKey");
Conclusion
Parcelable
est plus rapide que l' Serializable
interfaceParcelable
l'interface prend plus de temps à mettre en œuvre par rapport à l' Serializable
interfaceSerializable
l'interface est plus facile à mettre en œuvre Serializable
L'interface crée beaucoup d'objets temporaires et provoque un peu de collecte des orduresParcelable
le tableau peut être transmis via Intent dans AndroidSerializable est une interface Java standard. Vous marquez simplement une classe Serializable en implémentant l'interface, et Java la sérialisera automatiquement dans certaines situations.
Parcelable est une interface spécifique à Android où vous implémentez vous-même la sérialisation. Il a été créé pour être beaucoup plus efficace que Serializable et pour contourner certains problèmes avec le schéma de sérialisation Java par défaut.
Je crois que Binder et AIDL fonctionnent avec des objets Parcelable.
Cependant, vous pouvez utiliser des objets sérialisables dans Intents.
Parcelable vs Serializable Je fais référence à ces deux.
Pour Java et Kotlin
1) Java
Sérialisable, la simplicité
Qu'est-ce qui est sérialisable?
Serializable est une interface Java standard. Il ne fait pas partie du SDK Android. Sa simplicité est sa beauté. En mettant simplement en œuvre cette interface, votre POJO sera prêt à passer d'une activité à une autre.
public class TestModel implements Serializable {
String name;
public TestModel(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
La beauté de serializable est qu'il vous suffit d'implémenter l'interface Serializable sur une classe et ses enfants. Il s'agit d'une interface de marqueur, ce qui signifie qu'il n'y a pas de méthode à implémenter, Java fera simplement de son mieux pour la sérialiser efficacement.
Le problème avec cette approche est que la réflexion est utilisée et c'est un processus lent. Ce mécanisme a également tendance à créer un grand nombre d'objets temporaires et à provoquer un certain ramassage des ordures.
Parcelable, la vitesse
Qu'est-ce que Parcelable?
Parcelable est une autre interface. Malgré son rival (sérialisable au cas où vous l'auriez oublié), il fait partie du SDK Android. Maintenant, Parcelable a été spécifiquement conçu de telle manière qu'il n'y ait aucune réflexion lors de son utilisation. C'est parce que nous sommes vraiment explicites pour le processus de sérialisation.
public class TestModel implements Parcelable {
String name;
public TestModel(String name, String id) {
this.name = name;
}
protected TestModel(Parcel in) {
this.name = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() {
@Override
public TestModel createFromParcel(Parcel source) {
return new TestModel(source);
}
@Override
public TestModel[] newArray(int size) {
return new TestModel[size];
}
};
}
Maintenant, le gagnant est
Les résultats des tests effectués par Philippe Breault montrent que Parcelable est plus de 10 fois plus rapide que Serializable. Certains autres ingénieurs de Google soutiennent également cette déclaration.
Selon eux, l'approche Serializable par défaut est plus lente que Parcelable. Et ici, nous avons un accord entre les deux parties! MAIS, il est injuste de comparer ces deux! Parce qu'avec Parcelable, nous écrivons en fait du code personnalisé. Code spécialement créé pour ce POJO. Ainsi, aucune ordure n'est créée et les résultats sont meilleurs. Mais avec l'approche Serializable par défaut, nous nous appuyons sur le processus de sérialisation automatique de Java. Le processus n'est apparemment pas personnalisé du tout et crée beaucoup de déchets! Ainsi, les pires résultats.
Stop Stop !!!!, avant de prendre une décision
Maintenant, il y a une autre approche . L'ensemble du processus automatique derrière Serializable peut être remplacé par du code personnalisé qui utilise les méthodes writeObject () et readObject (). Ces méthodes sont spécifiques. Si nous voulons nous appuyer sur l'approche sérialisable en combinaison avec un comportement de sérialisation personnalisé, nous devons inclure ces deux méthodes avec la même signature exacte que celle ci-dessous:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
Et maintenant, une comparaison entre Parcelable et Serializable personnalisé semble juste! Les résultats peuvent être surprenants! L'approche Serializable personnalisée est plus de 3 fois plus rapide pour les écritures et 1,6 fois plus rapide pour les lectures que Parcelable.
Édité:-----
2) Sérialisation de Kotlinx
Bibliothèque de sérialisation Kotlinx
For Kotlin serialization need to add below dependency and plugin
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
apply plugin: 'kotlinx-serialization'
Votre build.gradle
dossier
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.smile.kotlinxretrosample"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
La sérialisation se fait assez facilement, vous devez annoter la classe voulue avec l' @Serializable
annotation comme ci-dessous
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
Deux autres annotations à noter sont transient
et optional
. L'utilisation de transitoire aura le sérialiseur ignorer ce champ et l'utilisation facultative permettra au sérialiseur de ne pas se casser si un champ est manquant, mais en même temps une valeur par défaut devra être fournie.
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
Remarque : Cela peut également fonctionner avec des classes de données.
Maintenant, pour réellement utiliser cela en action, prenons un exemple de la façon de convertir un JSON en objet et inversement
fun toObject(stringValue: String): Field {
return JSON.parse(Field.serializer(), stringValue)
}
fun toJson(field: Field): String {
//Notice we call a serializer method which is autogenerated from our class
//once we have added the annotation to it
return JSON.stringify(Field.serializer(), field)
}
Pour plus
Serialization
, Jetez un œil.
Si vous voulez être un bon citoyen, prenez le temps supplémentaire pour implémenter Parcelable car il fonctionnera 10 fois plus rapidement et utilisera moins de ressources.
Cependant, dans la plupart des cas, la lenteur de Serializable ne sera pas perceptible. N'hésitez pas à l'utiliser, mais n'oubliez pas que la sérialisation est une opération coûteuse, alors gardez-la au minimum.
Si vous essayez de passer une liste avec des milliers d'objets sérialisés, il est possible que l'ensemble du processus prenne plus d'une seconde. Il peut rendre les transitions ou la rotation du portrait au paysage très lentes.
Source à ce point: http://www.developerphil.com/parcelable-vs-serializable/
Dans Parcelable, les développeurs écrivent du code personnalisé pour le marshaling et le démarshaling afin de créer moins d'objets inutiles par rapport à la sérialisation. Les performances de Parcelable sur la sérialisation s'améliorent considérablement (environ deux fois plus vite), grâce à cette implémentation personnalisée.
Sérialisable est une interface de marqueur, ce qui implique que l'utilisateur ne peut pas rassembler les données en fonction de ses besoins. Dans la sérialisation, une opération de marshaling est effectuée sur une machine virtuelle Java (JVM) à l'aide de l'API de réflexion Java. Cela permet d'identifier le membre et le comportement de l'objet Java, mais finit également par créer de nombreux objets inutiles. Pour cette raison, le processus de sérialisation est lent par rapport à Parcelable.
Edit: Quelle est la signification de marshalling et unmarshalling?
En quelques mots, "marshalling" fait référence au processus de conversion des données ou des objets en un flux d'octets, et "unmarshalling" est le processus inverse de conversion du beack du flux d'octets en leurs données ou objets d'origine. La conversion est réalisée par "sérialisation".
En fait, je vais être le seul à défendre le sérialisable. La différence de vitesse n'est plus aussi drastique car les appareils sont bien meilleurs qu'il y a plusieurs années et il y a aussi d'autres différences plus subtiles. Voir mon article de blog sur la question pour plus d'informations.
Parcelable est l'approche recommandée pour les transferts de données. Mais si vous utilisez correctement sérialisable comme indiqué dans ce dépôt , vous verrez que sérialisable est parfois encore plus rapide que parcelable. Ou au moins les horaires sont comparables.
La sérialisation Java habituelle sur un appareil Android moyen (si bien fait *) est environ 3,6 fois plus rapide que Parcelable pour les écritures et environ 1,6 fois plus rapide pour les lectures. Cela prouve également que la sérialisation Java (si elle est effectuée correctement) est un mécanisme de stockage rapide qui donne des résultats acceptables même avec des graphiques d'objets relativement grands de 11 000 objets avec 10 champs chacun.
* Le sidenote est que généralement tous ceux qui déclarent aveuglément que "Parcelable est plus rapide" le comparent à la sérialisation automatique par défaut, qui utilise beaucoup de réflexion à l'intérieur. C'est une comparaison injuste, car Parcelable utilise une procédure manuelle (et très compliquée) d'écriture de données dans le flux. Ce qui n'est généralement pas mentionné, c'est que Java Serializable standard selon les documents peut également être fait de manière manuelle, en utilisant les méthodes writeObject () et readObject (). Pour plus d'informations, voir JavaDocs. C'est ainsi que cela doit être fait pour obtenir les meilleures performances.
La raison en est le code natif. Parcelable est créé non seulement pour la communication interprocessus. Il peut également être utilisé pour la communication intercode . Vous pouvez envoyer et recevoir des objets à partir de la couche native C ++. C'est tout.
Que choisir? Les deux fonctionnent bien. Mais je pense que Parcelable est un meilleur choix car il est recommandé par Google et comme vous pouvez le voir sur ce fil est beaucoup plus apprécié.
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@see http://developer.android.com/reference/android/os/Parcelable.html
Sachez que Serializable est une interface Java standard et Parcelable est destiné au développement Android.
Il y a un problème de performances concernant le marshaling et le démarshaling. Parcelable est deux fois plus rapide que Serializable.
Veuillez passer par le lien suivant:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
L'interface sérialisable peut être utilisée de la même manière que l'interface parcelable, ce qui entraîne (pas beaucoup) de meilleures performances. Remplacez simplement ces deux méthodes pour gérer le processus de marshaling et de dé-marshalling manuel:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
Pourtant, il me semble que lors du développement d'Android natif, l'utilisation de l'API Android est la voie à suivre.
Voir:
Je suis en retard dans la réponse, mais je poste avec l'espoir que cela aidera les autres.
En termes de vitesse , Parcelable > Serializable
. Mais, Serializable personnalisé est une exception. Il est presque à portée de Parcelable ou encore plus rapide.
Référence: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
Exemple :
Classe personnalisée à sérialiser
class MySerialized implements Serializable {
String deviceAddress = "MyAndroid-04";
transient String token = "AABCDS"; // sensitive information which I do not want to serialize
private void writeObject(ObjectOutputStream oos) throws Exception {
oos.defaultWriteObject();
oos.writeObject("111111" + token); // Encrypted token to be serialized
}
private void readObject(ObjectInputStream ois) throws Exception {
ois.defaultReadObject();
token = ((String) ois.readObject()).subString(6); // Decrypting token
}
}
Parcelable beaucoup plus rapide que sérialisable avec Binder, car sérialisable utilise la réflexion et provoque de nombreux GC. Parcelable est conçu pour optimiser pour passer l'objet.
Voici le lien vers la référence. http://www.developerphil.com/parcelable-vs-serializable/
vous pouvez utiliser les objets sérialisables dans les intentions mais au moment de faire sérialiser un objet Parcelable, il peut donner une exception sérieuse comme NotSerializableException. N'est-il pas recommandé d'utiliser sérialisable avec Parcelable. Il est donc préférable d'étendre Parcelable avec l'objet que vous souhaitez utiliser avec le bundle et les intentions. Comme ce Parcelable est spécifique à Android, il n'a donc aucun effet secondaire. :)
Sérialisable
Serializable est une interface marquable ou nous pouvons appeler une interface vide. Il n'a pas de méthodes pré-implémentées. Sérialisable va convertir un objet en flux d'octets. Ainsi, l'utilisateur peut transmettre les données d'une activité à une autre. Le principal avantage de la sérialisation est la création et la transmission de données est très facile mais c'est un processus lent comparé à la parcellaire.
Parcelable
Le colis est plus rapide que sérialisable. Parcel able va convertir l'objet en flux d'octets et transmettre les données entre deux activités. L'écriture de code capable de colis est un peu complexe par rapport à la sérialisation. Il ne crée pas plus d'objets temporaires en passant les données entre deux activités.