Android: Diferença entre Parcelável e Serializável?

313

Por que o Android fornece 2 interfaces para serializar objetos? Objetos serializáveis ​​interagem com Binderarquivos Android e AIDL?

live2dream95
fonte

Respostas:

444

No Android, não podemos simplesmente passar objetos para atividades. Para fazer isso, os objetos devem implementar Serializableou fazer Parcelableinterface.

Serializable

Serializableé uma interface Java padrão. Você pode simplesmente implementar a Serializableinterface e adicionar métodos de substituição. O problema com essa abordagem é que a reflexão é usada e é um processo lento. Esse método cria muitos objetos temporários e causa um pouco de coleta de lixo. No entanto, a Serializableinterface é mais fácil de implementar.

Veja o exemplo abaixo (serializável):

// 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

Parcelableprocesso é muito mais rápido que Serializable. Uma das razões para isso é que estamos sendo explícitos sobre o processo de serialização em vez de usar a reflexão para inferi-lo. Também é lógico que o código tenha sido fortemente otimizado para essa finalidade.

Veja o exemplo abaixo (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");

Você pode passar ArrayListobjetos Parcelable como abaixo:

// 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");

Conclusão

  1. Parcelableé mais rápido que a Serializableinterface
  2. Parcelableinterface leva mais tempo para implementar em comparação com a Serializableinterface
  3. Serializable interface é mais fácil de implementar
  4. Serializable interface cria muitos objetos temporários e causa um pouco de coleta de lixo
  5. Parcelable array pode ser passado via Intent no android
Sujith
fonte
2
@Sujith o que você quer dizer com reflexão é usada ? O que é reflexão ?
ANV
11
@AbhinavVutukuri Reflexão é o termo para inspecionar objetos, campos e métodos em tempo de execução via Object.getClass () e outros.
FaultException
2
Serializáveis ​​são melhores para dados persistentes; objetos parceláveis, por outro lado, não devem ser persistidos. É uma prática muito ruim
TheAnimatrix
2
@Sujith Como mais de uma pessoa afirmou, objetos Parcelable não podem ser persistidos (de maneira confiável), mas objetos Serializáveis ​​podem (dentro de limites). Como sua resposta é a de maior pontuação e dá a impressão de cobrir todas as diferenças importantes, você provavelmente deve mencionar esse ponto.
Larsh
4
Agora a implementação do Parcelable é tão rápida quanto a serializável, basta pressionar ALT + INSERT em qualquer classe que implemente o Parcelable no Android Studio e o IDE fará isso.
Ali Nem
183

Serializable é uma interface Java padrão. Você simplesmente marca uma classe como serializável implementando a interface, e o Java a serializa automaticamente em determinadas situações.

Parcelable é uma interface específica do Android em que você mesmo implementa a serialização. Ele foi criado para ser muito mais eficiente que o Serializable e para solucionar alguns problemas com o esquema de serialização Java padrão.

Acredito que Binder e AIDL funcionam com objetos Parcelable.

No entanto, você pode usar objetos serializáveis ​​no Intents.

Cheryl Simon
fonte
1
como serializar um objeto Parcelable? Como faço para persistir?
Hades
@Haded Obtenha o conteúdo do estado dos objetos e armazene-o em um arquivo ou banco de dados SQLLite. Seriliasing é útil para tornar objetos transferíveis entre diferentes componentes no Android ou em diferentes aplicativos.
Jonathan
6
Esta é uma ótima explicação. Também notei o seguinte: "O pacote não é um mecanismo de serialização de uso geral. Esta classe (e a API correspondente do Parcelable para colocar objetos arbitrários em um pacote) foi projetada como um transporte IPC de alto desempenho. Como tal, não é apropriado coloque quaisquer dados do Parcel no armazenamento persistente: alterações na implementação subjacente de qualquer um dos dados no Parcel podem tornar os dados mais antigos ilegíveis ". developer.android.com/reference/android/os/Parcel.html
Sam003 11/03/15
@Zhisheng, o que se entende por objetos arbitrários? que tipo de objetos podemos colocar no pacote?
hasnain_ahmad
Que tal converter objetos para json string em vez do gson?
FOO
57

Parcelável vs Serializável Refiro-me a esses dois.

Para Java e Kotlin

1) Java

Serializável, a simplicidade

O que é serializável?

Serializable é uma interface Java padrão. Não faz parte do SDK do Android. Sua simplicidade é sua beleza. Apenas implementando essa interface, seu POJO estará pronto para pular de uma atividade para outra.

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;
}
}
  • A beleza de serializável é que você só precisa implementar a interface serializável em uma classe e seus filhos. É uma interface de marcador, o que significa que não há método para implementar; o Java simplesmente fará o possível para serializá-lo de forma eficiente.

  • O problema com essa abordagem é que a reflexão é usada e é um processo lento. Esse mecanismo também tende a criar muitos objetos temporários e causar bastante coleta de lixo.

Parcelável, A Velocidade

O que é Parcelable?

Parcelable é outra interface. Apesar de seu rival (serializável no caso de você ter esquecido), ele faz parte do Android SDK. Agora, o Parcelable foi projetado especificamente de tal maneira que não há reflexo ao usá-lo. Isso é porque estamos sendo realmente explícitos para o processo de serialização.

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];
    }
};
}

Agora, o vencedor é

insira a descrição da imagem aqui

Os resultados dos testes realizados por Philippe Breault mostram que o Parcelable é 10 vezes mais rápido que o Serializable. Alguns outros engenheiros do Google também estão por trás dessa declaração.

Segundo eles, a abordagem serializável padrão é mais lenta que o Parcelable. E aqui temos um acordo entre as duas partes! MAS, é injusto comparar esses dois! Porque com o Parcelable, na verdade, estamos escrevendo código personalizado. Código criado especificamente para esse POJO. Assim, nenhum lixo é criado e os resultados são melhores. Mas com a abordagem serializável padrão, contamos com o processo de serialização automática de Java. O processo aparentemente não é personalizado e cria muito lixo! Assim, os piores resultados.

Stop Stop !!!!, Antes de tomar uma decisão

Agora, há outra abordagem . Todo o processo automático por trás do Serializable pode ser substituído pelo código personalizado que usa os métodos writeObject () & readObject (). Esses métodos são específicos. Se quisermos confiar na abordagem serializável em combinação com o comportamento de serialização personalizado, devemos incluir esses dois métodos com a mesma assinatura exata da abaixo:

 private void writeObject(java.io.ObjectOutputStream out)
 throws IOException;

 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

 private void readObjectNoData()
     throws ObjectStreamException;

E agora uma comparação entre Parcelable e Custom Serializable parece justa! Os resultados podem ser surpreendentes! A abordagem serializável personalizada é mais do que 3x mais rápida para gravações e 1,6x mais rápida para leituras do que o Parcelable.

Editado:-----

2) Serialização Kotlinx

Biblioteca de serialização da 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'

Seu build.gradlearquivo

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'
}

A serialização é feita com bastante facilidade; você precisa anotar a classe pretendida com a @Serializableanotação conforme abaixo

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

Mais duas anotações a serem observadas são transiente optional. O uso de transitório fará com que o serializador ignore esse campo e o uso de opcional permitirá que o serializador não quebre se um campo estiver faltando, mas, ao mesmo tempo, será necessário fornecer um valor padrão.

@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false

Nota : Isso também pode funcionar com classes de dados.

Agora, para realmente usar isso em ação, vamos dar um exemplo de como converter um JSON em objeto e voltar

 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)
    }

Para mais

Farhana
fonte
@ Farhana Como fazer isso para a classe de dados no kotlin?
Nisarg 04/10/19
@Nisarg Adicionei Kotlin Serialization, dê uma olhada.
Farhana
@ Farhana Isso foi muito esclarecedor. Eu realmente quero mudar para o kotlin no trabalho, mas minha proposta é constantemente rejeitada pelos gerentes. Gostaria de saber se posso obter benchmark para Serializable (com método personalizado) que você diz ser 1,6 vezes mais rápido que Parcelable.
Abhinav Kulshreshtha 21/01
39

Se você deseja ser um bom cidadão, dedique um tempo extra à implementação do Parcelable, pois ele será executado 10 vezes mais rápido e usará menos recursos.

No entanto, na maioria dos casos, a lentidão de Serializable não será perceptível. Sinta-se à vontade para usá-lo, mas lembre-se de que a serialização é uma operação cara, portanto, mantenha-o no mínimo.

Se você estiver tentando passar uma lista com milhares de objetos serializados, é possível que todo o processo demore mais de um segundo. Pode fazer com que as transições ou a rotação do retrato para a paisagem pareçam muito lentas.

Fonte para este ponto: http://www.developerphil.com/parcelable-vs-serializable/

codercat
fonte
32

No Parcelable, os desenvolvedores escrevem código personalizado para empacotamento e desempacotamento, criando menos objetos de lixo em comparação com a serialização. O desempenho do Parcelable over Serialization melhora drasticamente (cerca de duas vezes mais rápido), devido a essa implementação personalizada.

Serializable é uma interface de marcador, que implica que o usuário não pode organizar os dados de acordo com seus requisitos. Na serialização, uma operação de empacotamento é executada em uma Java Virtual Machine (JVM) usando a API de reflexão do Java. Isso ajuda a identificar o membro e o comportamento do objeto Java, mas também acaba criando muitos objetos de lixo. Devido a isso, o processo de serialização é lento em comparação com o Parcelable.

Edit: Qual é o significado de marshalling e unsailing?

Em poucas palavras, "empacotamento" refere-se ao processo de conversão de dados ou objetos em um fluxo de bytes, e "desempacotamento" é o processo inverso de conversão do bloco de fluxo de bytes em seus dados ou objetos originais. A conversão é alcançada através de "serialização".

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

Uts
fonte
Explicação muito boa, mesmo sem um exemplo detalhado. Apenas o que eu precisava para revisão.
sud007
20

Na verdade, eu vou ser o cara que defende o Serializable. A diferença de velocidade não é mais tão drástica, já que os dispositivos são muito melhores do que vários anos atrás e também existem outras diferenças mais sutis. Veja minha postagem no blog para obter mais informações.

Nemanja Kovacevic
fonte
1
Obrigado pela participação. Sua implementação menos complexa é serializável e o trade-off precisa ser decidido nesses casos raros e de hiper otimização.
Ankan-Zerob
2
O ponto de vista alternativo, especialmente quando apoiado em experimentos e resultados, é muito útil. Tenho que trabalhar com muitos códigos-fonte baseados em Parcelable existentes e refatorar alguns deles agora que li sua postagem no blog.
Les
14

Parcelable é uma espécie de padrão no desenvolvimento do Android. Mas não por causa da velocidade

Parcelable é a abordagem recomendada para transferências de dados. Porém, se você usar serializável corretamente, como mostrado neste repositório , verá que o serializável às vezes é ainda mais rápido que o parcelável. Ou pelo menos os horários são comparáveis.

O Parcelable é mais rápido que o Serializable?

A serialização Java comum em um dispositivo Android médio (se bem feito *) é cerca de 3,6 vezes mais rápida que o Parcelable para gravações e 1,6 vezes mais rápida para leituras. Também prova que a serialização Java (se bem feita) é um mecanismo de armazenamento rápido que fornece resultados aceitáveis, mesmo com gráficos de objetos relativamente grandes de 11000 objetos com 10 campos cada.

* A nota de rodapé é que geralmente todo mundo que cegamente declara que "O pacote é mais rápido" o compara à serialização automática padrão, que usa muita reflexão por dentro. Essa é uma comparação injusta, porque o Parcelable usa o procedimento manual (e muito complicado) de gravar dados no fluxo. O que geralmente não é mencionado é que o Java Serializable padrão, de acordo com os documentos, também pode ser feito de maneira manual, usando os métodos writeObject () e readObject (). Para mais informações, consulte JavaDocs. É assim que deve ser feito para o melhor desempenho.

Então, se o serializable é mais rápido e fácil de implementar, por que o Android é parcelável?

O motivo é o código nativo. Parcelable é criado não apenas para comunicação entre processos. Também pode ser usado para comunicação intercode . Você pode enviar e receber objetos da camada nativa do C ++. É isso aí.

O que você deve escolher? Ambos irão funcionar bem. Mas acho que o Parcelable é a melhor escolha, pois é recomendado pelo google e, como você pode ver neste tópico, é muito mais apreciado.

Maksim Turaev
fonte
Você pode site suas fontes? Eu realmente apreciaria isto. Obrigado!!
Archie G. Quiñones
2
Essa resposta recebi de um desenvolvedor experiente que trabalha no projeto relacionado à AOSP twitter.com/bwdude . Ele disse que o código C ++ nativo para comunicação com a camada SDK usa sua própria implementação do Parcelable. Acho que ele falou sobre essa classe android.googlesource.com/platform/frameworks/native/+/… Eu sei que essa não é a melhor explicação, mas é a melhor que tenho agora. Se você vai encontrar algo mais, não se esqueça de postar aqui =)
Maksim Turaev
Gostaria de poder te votar mais de uma vez. Vi grandes especialistas em Android e Java buscarem a resposta mais votada aqui. A falta de documentação realmente impediu qualquer destaque para o Serializable. Parece que esses são efeitos da promoção de uma API específica. Obrigado!
Pulp_fiction 21/07/19
11

1. Serializável

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

Interface de quê?

  • é uma interface Java padrão

Rapidez

  • mais lento que o Parcelable

2. Parcelável

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

Interface de quê?

  • é a interface android.os
    • o que significa que o Google desenvolveu o Parcelable para obter melhor desempenho no Android

Rapidez

  • mais rápido (porque é otimizado para uso no desenvolvimento do Android)

> Em conclusão

Esteja ciente de que Serializable é uma interface Java padrão e Parcelable é para desenvolvimento do Android

kenju
fonte
Você deve adicionar os usos deles também.
Anshul Tyagi
4

A implementação do parcelable pode ser mais rápida se você usar o plugin paracelable no android studio. procurar gerador de código para Android Parcelable

Deep P
fonte
3

A interface serializável pode ser usada da mesma maneira que a interface Parcelable, resultando em (não muito) melhores desempenhos. Basta substituir esses dois métodos para lidar com o processo manual de empacotamento e descompactação:

private void writeObject(java.io.ObjectOutputStream out)
    throws IOException
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException

Ainda assim, parece-me que, ao desenvolver o Android nativo, usar a API do Android é o caminho a percorrer.

Vejo :

Ceilão
fonte
2

Estou atrasado em responder, mas postando com esperança de que isso ajude outras pessoas.

Em termos de velocidade , Parcelable > Serializable. Mas, Serializable personalizado é exceção. É quase na faixa de Parcelable ou ainda mais rápido.

Referência: https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/

Exemplo:

Classe personalizada a ser serializada

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
fonte
1

você pode usar os objetos serializáveis ​​nas intenções, mas no momento de serializar um objeto Parcelable, isso pode causar uma exceção séria, como NotSerializableException. Não é recomendado o uso de serializável com Parcelable. Portanto, é melhor estender o Parcelable com o objeto que você deseja usar com o pacote e as intenções. Como este Parcelable é específico para o Android, não tem efeitos colaterais. :)

Rankush Kumar
fonte
0

Serializable

Serializable é uma interface marcável ou podemos chamar como uma interface vazia. Não possui métodos pré-implementados. Serializable vai converter um objeto em fluxo de bytes. Assim, o usuário pode passar os dados entre uma atividade para outra. A principal vantagem do serializable é a criação e a transmissão de dados é muito fácil, mas é um processo lento comparado ao parcelable.

Parcelable

O pacote é mais rápido que o serializável. O Parcelable vai converter o objeto em fluxo de bytes e transmitir os dados entre duas atividades. Escrever código de pacote é um pouco complexo comparado à serialização. Ele não cria mais objetos temporários ao passar os dados entre duas atividades.

Cprk Praveen
fonte