Transmitindo dados com intenção
É fácil passar tipos de dados simples (String, int, double, … ect) entre as atividades. Nós podemos apenas colocar a eles a intenção com chave única e enviá-lo para uma outra atividade.
Mas é um pouco complexo ao passar objetos personalizados entre atividades. Este é o lugar de onde
serialization
vem.
O que é serialização?
A serialização é a conversão de dados de uma representação interna rápida e eficiente em algo que pode ser mantido em um armazenamento persistente ou transmitido por uma rede.
A conversão de dados em seu formato serializado costuma ser chamada de
marshaling
. Convertê-lo de volta à sua representação ao vivo na memória é chamado de desserialização ouunmarshaling
.
Mais sobre serialização – https://www.inkling.com/read/programming-android-mednieks-1st/chapter-6/serialization
- No Android, existem duas maneiras de alcançar
marshaling
eunmarshaling
de objetos java
- Serializable (objeto de implementação como Serializable)
- Parcelable (Implementar objeto como Parcelable)
Serializável vs Parcelável
Serializable é uma interface de marcador, o que significa que o usuário não pode empacotar os dados de acordo com seus requisitos. Portanto, quando o objeto implementa, o
Serializable
Java o serializa automaticamente.Parcelable é o próprio protocolo de serialização do Android. No Parcelable, os desenvolvedores escrevem código personalizado para empacotamento e desempacotamento. Portanto, ele cria menos objetos de lixo em comparação com a serialização
O desempenho de Parcelable é muito alto quando comparado a Serializable por causa de sua implementação personalizada
É altamente recomendável usar a implantação Parcelable ao serializar objetos no Android
Objetos parceláveis
Quando for necessário passar um objeto personalizado entre as atividades, podemos marcar o objeto como Parcelable (Implementar a interface Parcelable). Então, o objeto é capaz de colocar em um intent com o método
intent.putExtra
A seguir está um exemplo de implementação de objeto parcelable (
User
)
https://github.com/erangaeb/dev-notes/blob/master/android-parcelable/User.java
Este é um objeto simples que mantém os dados relacionados ao usuário.
User
objeto implementa como Parcelable.Existem dois métodos para sobrescrever na
Parcelable
interfacedescribeContents
ewriteToParcel
. A serialização real do objeto faz nowriteToParcel
método.
/**
* Define the kind of object that you gonna parcel,
* You can use hashCode() here
*/
@Override
public int describeContents() {
return 0;
}
/**
* Actual object serialization happens here, Write object content
* to parcel, reading should be done according to this write order
* param dest - parcel
* param flags - Additional flags about how the object should be written
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(username);
dest.writeString(email);
dest.writeString(password);
}
- Objeto precisa ter . Este campo é necessário para que o Android possa criar novos objetos, individualmente ou como matrizes
Parcelable.Creator
/**
* This field is needed for Android to be able to
* create new objects, individually or as arrays
*
* If you don’t do that, Android framework will raises an exception
* Parcelable protocol requires a Parcelable.Creator object
* called CREATOR
*/
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
public User createFromParcel(Parcel in) {
return new User(in);
}
public User[] newArray(int size) {
return new User[size];
}
};
Este objeto User é um objeto parcelabel simples. Pode haver alguns objetos mais complexos, por exemplo, você tem um objeto que faz referência a outro objeto. Nesse tipo de cenário, eles precisariam ser Parceláveis
A seguir está um exemplo de objeto parcelável mais complexo (
Sensor
)
https://github.com/erangaeb/dev-notes/blob/master/android-parcelable/Sensor.java
Sensor
objeto contém alguns campos especiais
1. User object(user)
2. User list(sharedUsers)
3. boolean field(isMySensor)
- Ao gravar o
user
objeto do sensor no pacote, ele usa
dest.writeParcelable(user, flags);
- Ao ler o
user
objeto do pacote, ele precisa do carregador de classe
this.user = in.readParcelable(User.class.getClassLoader());
- Ao escrever a lista de usuário (
sharedUsers
) para o pacote, ele usa
dest.writeTypedList(sharedUsers);
- Ao ler a lista de usuários (
sharedUsers
) do pacote, ele precisa de instânciaUser.CREATOR
this.sharedUsers = new ArrayList<User>();
in.readTypedList(sharedUsers, User.CREATOR);
- Em vez de escrever o valor booleano na parcela, nós o convertemos em um valor inteiro e o salvamos como um inteiro (uma vez que nenhum método para escrever booleanos diretamente na parcela)
dest.writeInt(isMySensor ? 1 : 0);
- Ao ler o valor booleano, obtemos o valor booleano do inteiro salvo
this.isMySensor = (in.readInt() != 0);
Passe o objeto com intenção
- Ao iniciar a atividade, podemos definir o objeto parcelável para uma intenção
User user = new User("1", "u", "u", "u");
ArrayList<User> userList = new ArrayList<User>();
Sensor sensor = new Sensor("1", "s", "s", true, user, userList);
intent.putExtra("com.score.senzors.pojos.Sensor", sensor);
- Na atividade de destino, podemos obter o objeto parcelável de extras de intent (pacote)
Bundle bundle = getIntent().getExtras();
Sensor sensor = bundle.getParcelable("com.score.senzors.pojos.Sensor")