Um argumento semelhante, mesmo que um pouco mais fraco, se aplica à utilização de state.toString() para criar uma representação serializada de do tipo State. O mapeamento entre um objeto e sua representação em um Parcel faz parte do procedimento específico de serialização. Não se trata de um atributo inerente ao objeto. É inteiramente possível que certo objeto tenha representações completamente diferentes quando serializado por serializadores distintos. Para ilustrar esse princípio – ainda que provavelmente estejamos exagerando, pois o tipo State é localmente definido-, o mapa utilizado para serializar state é um membro independente e explicitamente definido apenas para a serialização.
SimpleParcelable, como mostramos antes, compila sem nenhum erro. Ele poderia até mesmo ser serializado como um pacote. Até aqui, entretanto, não temos como pegá-lo de volta. Para isso necessitamos de um desserializador conforme demonstrado pelo restante do código abaixo:
//CODIGO OMITIDO....}
private static final Map<String, State>unmarshalState ;
static {Map<String, State> m =}new HashMap<String, State>();
m.put("begin" , State.BEGIN );
m.put("middle" , State.MIDDLE );
m.put("end" , State.END );
unmarshalState = Collections.unmodifiableMap(m);
private Statestate ;
private Datedate ;
public static final Parcelable.Creator<SimpleParcelable>CREATOR =new Parcelable.Creator<SimpleParcelable>() {};public SimpleParcelable createFromParcel(Parcel in) {}return new SimpleParcelable(in.readLong(), in.readString());public SimpleParcelable[] newArray(int size) {}return new SimpleParcelable[size];public SimpleParcelable(long date, String state) {} //CODIGO OMITIDO....if (date >= 0) {}this .date =new Date(date);if (state !=null && state.length() > 0) {}this .state =unmarshalState .get(state);
O trecho de código acima mostra apenas o desserializador recém adicionado, o campo final, estático e público chamado CREATOR. O campo é uma referência a uma implementação de Parcelable.Creator<T>, em que “T” é o tipo do objeto empacotável que será desserializado, nesse caso específico, um SimpleParcelable. É importante que isso seja feito de forma correta! Se CREATOR for protegido em vez de público, se não for estático, ou se estiver escrito “Creator”, o framework do Android não poderá desserializar o objeto em questão.
A implementação de Parcelable.Creator<T> é um objeto com um único método, createFromParcel, que desserializa uma única instância de Parcel. Isso deve ser feito de forma idiomática, ou seja, lendo cada seção de dados do Parcel exatamente na mesma ordem em que eles foram escritos em writeToParcel. Essa ordem de leitura é essencial e fundamental para que o procedimento de serializar/desserializar seja correto. No caso do código genérico de exemplo representado pela classe SimpleParcelable, primeiro foi escrito (writeToParcel) um long que representa a data e segundo foi escrito uma string que representa o state. Desta forma, a desserialização (CREATOR) deve ler, primeiro, um long e, depois, uma string, nesta ordem.
|
Não respeitar a ordem é um erro grave de programação. Uma vez lido corretamente os dados, chama-se o construtor da classe passando como parâmetro os estado recuperado/desserializado. Como o construtor de desserialização é chamado a partir do escopo da própria classe, ele pode ser protegido em nível de pacote ou até mesmo privado.
|