Android: Différence entre Parcelable et Serializable?

313

Pourquoi Android propose-t-il 2 interfaces pour sérialiser des objets? Les objets sérialisables interagissent-ils avec les Binderfichiers Android et AIDL?

live2dream95
la source

Réponses:

444

Dans Android, nous ne pouvons pas simplement transmettre des objets à des activités. Pour ce faire, les objets doivent implémenter Serializableou Parcelableinterfacer.

Sérialisable

Serializableest une interface Java standard. Vous pouvez simplement implémenter l' Serializableinterface 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' Serializableinterface 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

Parcelableprocessus 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 ArrayListd'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

  1. Parcelableest plus rapide que l' Serializableinterface
  2. Parcelablel'interface prend plus de temps à mettre en œuvre par rapport à l' Serializableinterface
  3. Serializable l'interface est plus facile à mettre en œuvre
  4. Serializable L'interface crée beaucoup d'objets temporaires et provoque un peu de collecte des ordures
  5. Parcelable le tableau peut être transmis via Intent dans Android
Sujith
la source
2
@Sujith qu'entendez-vous par réflexion ? Qu'est-ce que la réflexion ?
AnV
11
@AbhinavVutukuri Reflection est le terme utilisé pour inspecter des objets, des champs et des méthodes au moment de l'exécution via Object.getClass () et autres.
FaultException du
2
Les sérialisables sont meilleurs pour les données persistantes, les objets parcellaires en revanche ne devraient pas du tout être persistants. C'est une très mauvaise pratique
TheAnimatrix
2
@Sujith Comme plus d'une personne l'a déclaré, les objets parcellables ne peuvent pas être persistants (de manière fiable), mais les objets sérialisables peuvent (dans certaines limites). Puisque votre réponse est la meilleure note et donne l'impression de couvrir toutes les différences importantes, vous devriez probablement mentionner ce point.
LarsH
4
Maintenant, l'implémentation de Parcelable est aussi rapide que Serializable, appuyez simplement sur ALT + INSERT sur n'importe quelle classe implémentant Parcelable dans Android Studio et l'IDE le fera.
Ali Nem
183

Serializable 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.

Cheryl Simon
la source
1
comment sérialiser un objet Parcelable? Comment puis-je le rendre persistant?
Hadès
@Haded Récupère le contenu de l'état des objets et le stocke dans un fichier ou une base de données SQLLite. Le seriliasing est utile pour rendre des objets transférables entre différents composants dans Android ou différentes applications.
Jonathan
6
Ceci est une excellente explication. J'ai également remarqué ceci: "Parcel n'est pas un mécanisme de sérialisation à usage général. Cette classe (et l'API Parcelable correspondante pour placer des objets arbitraires dans un Parcel) est conçue comme un transport IPC hautes performances. En tant que tel, il n'est pas approprié de placer toutes les données de la parcelle dans un stockage persistant: les changements dans l'implémentation sous-jacente de l'une des données de la parcelle peuvent rendre les données plus anciennes illisibles. " developer.android.com/reference/android/os/Parcel.html
Sam003
@Zhisheng qu'entend-on par objets arbitraires? quel type d'objets pouvons-nous mettre dans le colis?
hasnain_ahmad
Que diriez-vous de convertir des objets en chaîne json à la place avec gson?
FOO
57

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

entrez la description de l'image ici

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.gradledossier

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' @Serializableannotation comme ci-dessous

import kotlinx.serialization.Serializable
@Serializable
class Field {
    var count: Int = 0
    var name: String = ""
}

Deux autres annotations à noter sont transientet 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

Farhana
la source
@Farhana Comment faire pour la classe de données dans kotlin?
Nisarg
@Nisarg J'ai ajouté Kotlin Serialization, Jetez un œil.
Farhana
@Farhana C'était très perspicace. Je veux vraiment passer à kotlin au travail mais ma proposition est constamment rejetée par les managers. Je me demande si je peux obtenir une référence pour Serializable (avec une méthode personnalisée) qui, selon vous, est 1,6 fois plus rapide que Parcelable.
Abhinav Kulshreshtha
39

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/

codercat
la source
32

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".

http://www.jguru.com/faq/view.jsp?EID=560072

Uts
la source
Très bonne explication même sans un exemple détaillé. Exactement ce dont j'avais besoin pour une révision.
sud007
20

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.

Nemanja Kovacevic
la source
1
Merci pour le partage. Son moins complexe à mettre en œuvre sérialisable et le compromis doit être décidé dans ces cas rares et hyper optimisation.
Ankan-Zerob
2
Le point de vue alternatif, en particulier lorsqu'il est soutenu par des expériences et des résultats, est très utile. Je dois travailler avec beaucoup de code source basé sur Parcelable et je peux en refactoriser une partie maintenant que j'ai lu votre article de blog.
Les
14

Parcelable est une sorte de standard dans le développement Android. Mais pas à cause de la vitesse

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.

Parcelable est-il plus rapide que sérialisable?

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.

Donc, si la sérialisation est plus rapide et plus facile à implémenter, pourquoi Android a-t-il du tout du lot?

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é.

Maksim Turaev
la source
Pouvez-vous site vos sources? J'apprécierai vraiment cela. Merci!!
Archie G. Quiñones
2
Cette réponse m'a été fournie par un développeur expérimenté qui travaille sur le projet lié à AOSP twitter.com/bwdude . Il a déclaré que le code C ++ natif pour la communication avec la couche SDK utilise sa propre implémentation de Parcelable. Je suppose qu'il parle de cette classe android.googlesource.com/platform/frameworks/native/+/… Je sais que ce n'est pas la meilleure explication, mais c'est la meilleure que j'ai en ce moment. Si vous trouverez autre chose, assurez-vous de le poster ici =)
Maksim Turaev
J'aimerais pouvoir vous voter plus d'une fois. J'ai vu de grands experts Android et Java chercher la réponse la plus appréciée ici. Le manque de documentation a vraiment empêché toute mise en lumière pour Serializable. On dirait que ce sont des effets de la promotion d'une API spécifique. Merci!
pulp_fiction
11

1. Sérialisable

@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

Interface de quoi?

  • est une interface Java standard

La vitesse

  • plus lent que Parcelable

2. Colisable

@see http://developer.android.com/reference/android/os/Parcelable.html

Interface de quoi?

  • est l'interface android.os
    • ce qui signifie que Google a développé Parcelable pour de meilleures performances sur Android

La vitesse

  • plus rapide (car il est optimisé pour une utilisation sur le développement Android)

> En conclusion

Sachez que Serializable est une interface Java standard et Parcelable est destiné au développement Android.

kenju
la source
Vous devez également ajouter leur utilisation.
Anshul Tyagi
4

L'implémentation de parcelable peut être plus rapide si vous utilisez le plugin paracelable dans Android Studio. rechercher le générateur de code Android Parcelable

Deep P
la source
3

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:

Ceyfiroth
la source
2

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
    }

}
Kushal
la source
1

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. :)

Rankush Kumar
la source
0

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.

Cprk Praveen
la source