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?

Imersão dev Back-end: mergulhe em programação hoje, com a Alura e o Google Gemini. Domine o desenvolvimento back-end e crie o seu primeiro projeto com Node.js na prática. O evento é 100% gratuito e com certificado de participação. O período de inscrição vai de 18 de novembro de 2024 a 22 de novembro de 2024. Inscreva-se já!

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