Por que o Android fornece 2 interfaces para serializar objetos? Objetos serializáveis interagem com Binder
arquivos Android e AIDL?
Por que o Android fornece 2 interfaces para serializar objetos? Objetos serializáveis interagem com Binder
arquivos Android e AIDL?
Respostas:
No Android, não podemos simplesmente passar objetos para atividades. Para fazer isso, os objetos devem implementar Serializable
ou fazer Parcelable
interface.
Serializable
Serializable
é uma interface Java padrão. Você pode simplesmente implementar a Serializable
interface 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 Serializable
interface é 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
Parcelable
processo é 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 ArrayList
objetos 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
Parcelable
é mais rápido que a Serializable
interfaceParcelable
interface leva mais tempo para implementar em comparação com a Serializable
interfaceSerializable
interface é mais fácil de implementar Serializable
interface cria muitos objetos temporários e causa um pouco de coleta de lixoParcelable
array pode ser passado via Intent no androidSerializable é 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.
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 é
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.gradle
arquivo
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 @Serializable
anotaçã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 transient
e 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
Serialization
, dê uma olhada.
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/
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".
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.
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.
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.
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.
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@see http://developer.android.com/reference/android/os/Parcelable.html
Esteja ciente de que Serializable é uma interface Java padrão e Parcelable é para desenvolvimento do Android
Há algum problema de desempenho relacionado à empacotamento e descompactação. Parcelable é duas vezes mais rápido que Serializable.
Por favor, acesse o seguinte link:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
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 :
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
}
}
Parcelável muito mais rápido que o serializável com o Binder, porque o serializável usa reflexão e causa muitos GC. Parcelable é design para otimizar a passagem do objeto.
Aqui está o link para referência. http://www.developerphil.com/parcelable-vs-serializable/
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. :)
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.