Início > Padrão de Projeto > Quem nunca recebeu um NullPointException que atire a primeira pedra !

Quem nunca recebeu um NullPointException que atire a primeira pedra !

O desenvolvedor nunca recebeu um NullPointerException que atire a primeira pedra. Há diversas formas de se receber esse tipo de exceção não tratável. Há uns meses, quando comecei a desenvolver um projeto de médio porte, tive a necessidade de criar várias telas (no meu caso criei as telas com XML) com componentes dentro dela. Cada componente da sua tela tem um Id que serve para identifica-lo. Foi nesse momento que começou a dor de cabeça o NullPointerException que começaram a aparecer devido às referências dos componentes. No decorrer deste artigo, será exemplificado (via código) o problema e a solução para identificar um NullPointerException provocado por referências de componentes com o mesmo nome.

 


Problema que tive
Tenho o costume de criar uma Activity para cada tela (acho que 99,9% dos desenvolvedores também fazem isso). Na criação das telas no XML, adicionei o componente do tipo TextView com o ID “nome” em todas elas, ou seja, Tela1, Tela2 e Tela3 possuem um textView com o mesmo ID: “nome”. A invocação desse componente na Activity ficaria assim:

Public class Tela1 extends Activity {
       Private TextView textName;
        public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);
	   setContentView(R.layout.main);
	   this.textName = (TextView)findViewById(R.id.nome);

   }
}
Public class Tela2 extends Activity {
       Private TextView textName;
        public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);
	   setContentView(R.layout.main2);
	   this.textName = (TextView)findViewById(R.id.nome);

   }
}

 

Public class Tela3 extends Activity {
       Private TextView textName;
        public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState);
	   setContentView(R.layout.main3);
	   this.textName = (TextView)findViewById(R.id.nome);

   }
}

É importante notar que nos 3 exemplos de código acima, no método setContentView, é setado um XML para cada Activity. Os arquivos XML ficariam como segue abaixo:

Main.xml


<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+id/nome”
/>

Main2.xml

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+id/nome”
/>

Main3.xml

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+id/nome”
/>

Digamos que precisemos alterar o nome do componente TextView da Tela1 de “nome” para “textNome”, ficando da seguinte forma:

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+id/textNome”
/>

Será que a linha de código abaixo, presente no arquivo main.xml, apresentará erro de compilação?

this.textName = (TextView)findViewById(R.id.nome); 

A resposta é NÃO, porque você estará acessando R.id.nome presentes nos arquivos main2.xml (Tela2) ou main3.xml (Tela3). Eu recebia um NullPointerException porque eu acessava um componente de uma View da qual não tenho acesso. Quando foram escritos os arquivos main.xml, main2.xml e main3.xml foi dado o mesmo nome identificador a componentes diferentes.

Solução do problema
Comecei a procurar na internet uma solução elegante para resolver esse problema e consegui achar na documentação do Android a informação que precisava. No atributo ID dos componentes do XML não é necessário ter o nome “id” após o @+, observe a linha 4. Pode ser outro nome. Exemplo:

Main.xml

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+idMain/nome”
/>

Main2.xml

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+idMain2/nome”
/>

Main3.xml

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id=”@+idMain3/nome”
/>

E agora eu acesso os componentes na minha Activity dessa maneira:

this.textName = (TextView)findViewById(R.idMain.nome); 
this.textName = (TextView)findViewById(R.idMain2.nome);
this.textName = (TextView)findViewById(R.idMain3.nome);

Assim, consigo visualizar exatamente aquele componente da minha View.

Anúncios
  1. diogo
    janeiro 6, 2012 às 2:37 pm

    Eu conheço esse post!! Um cara numa empresa que eu trabalhei aplicou exatamente esse padrão!!

  1. No trackbacks yet.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: