Intent: passando objetos com campos não serializáveis

Intent: passando objetos com campos não serializáveis
felipe.torres
felipe.torres

Compartilhe

Suponha a seguinte classe Aluno:

 public class Aluno { private String nome; private String telefone;

public Aluno(String nome, String telefone) { this.nome = nome; this.telefone = telefone; } } 

Como faríamos para passar uma instância dessa classe para uma Activity?

Banner promocional da Alura, com chamada para um evento ao vivo no dia 12 de fevereiro às 18h30, com os dizeres

Como visto nos cursos de Android da Caelum, poderiamos usar o método putExtra() da Intent para isso:

 Aluno aluno = new Aluno("Felipe", "555-1234");

Intent intent = new Intent(this, OutraActivity.class); intent.putExtra("aluno", aluno); startActivity(intent); 

Porém, o putExtra() não é capaz de receber um Aluno! Então, temos que implementar a interface Serializable:

 public class Aluno implements Serializable { //... } 

Agora a classe Aluno é capaz de serializar todos os seus atributos que podem ser serializáveis. Porém, o que acontece se a classe Aluno possuir algum atributo que não é serializável?

Um exemplo disso seria colocar um atributo Context na nossa classe para exibir um Toast:

 public class Aluno { private String nome; private String telefone; private Context context = CaixaPreta.getContext();

public Aluno(String nome, String telefone) { this.nome = nome; this.telefone = telefone; }

public void mostraNome() { Toast.makeText(context, this.nome, Toast.LENGTH\_LONG).show(); } } 

Como Context não é serializável, teremos uma java.io.NotSerializableException ao chamar o putExtra()!

Para resolver esse problema, podemos simplesmente ignorar o campo Context na serialização por meio do modifier transient:

 public class Aluno { private String nome; private String telefone; private transient Context context = CaixaPreta.getContext();

public Aluno(String nome, String telefone) { this.nome = nome; this.telefone = telefone; }

public void mostraNome() { Toast.makeText(context, this.nome, Toast.LENGTH\_LONG).show(); } } 

Como poderemos chamar o método mostraNome() após recuperar o aluno na OutraActivity?

 Intent intent = getIntent(); Aluno recuperado = (Aluno) intent.getSerializableExtra("aluno");

recuperado.mostraNome(); 

Como ignoramos o campo Context, ao recuperar o aluno o conteúdo de context será null.

À primeira vista, poderíamos popular o context no construtor do Aluno:

 public Aluno(String nome, String telefone) { this.nome = nome; this.telefone = telefone; this.context = CaixaPreta.getContext(); } 

Porém, o processo de desserialização não chama o construtor da classe. Então ainda teremos um null no context.

Ao fazer a desserialização do nosso aluno podemos implementar um método chamado readObject, responsável por popular os campos do objeto desseralizado.

 public class Aluno { private String nome; private String telefone; private transient Context context = CaixaPreta.getContext();

public Aluno(String nome, String telefone) { this.nome = nome; this.telefone = telefone; }

public void mostraNome() { Toast.makeText(context, this.nome, Toast.LENGTH\_LONG).show(); }

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); this.context = CaixaPreta.getContext(); } } 

Com isso, podemos passar o Aluno para uma outra Activity e repopular o campo que não é serializável!

Veja outros artigos sobre Mobile