Passando objetos entre atividades no Android

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

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 ou unmarshaling.

Mais sobre serialização – https://www.inkling.com/read/programming-android-mednieks-1st/chapter-6/serialization

  • No Android, existem duas maneiras de alcançar marshalinge unmarshalingde objetos java
  1. Serializable (objeto de implementação como Serializable)
  2. 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 SerializableJava 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étodointent.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. Userobjeto implementa como Parcelable.

  • Existem dois métodos para sobrescrever na Parcelableinterface describeContentse writeToParcel. A serialização real do objeto faz no writeToParcelmé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 matrizesParcelable.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 userobjeto do sensor no pacote, ele usa
dest.writeParcelable(user, flags);
  • Ao ler o userobjeto 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")