Android: Alternativa para o findViewById
Overview
Se você, assim como muitos desenvolvedores Android, encontra-se frequentemente frustrado com a complexidade do binding de elementos de layout, este tutorial é para você! Vamos mergulhar numa abordagem simplificada utilizando a Data Binding Library, eliminando a necessidade do tedioso findViewById. Este guia é ideal para quem busca otimizar seu fluxo de trabalho no Android Studio, deixando mais tempo para o que realmente importa: criar apps incríveis.
Quando estamos criando algo para a plataforma Android, uma das coisas que mais me fazem querer largar o que estou desenvolvendo e ir ver uma série no Netflix é a forma como é feita o binding entre os elementos do layout com a classe. Ter que declarar os elementos, utilizar o tal do findViewById… Arrgh! Bom, este tutorial ensina uma forma mais simples de tratar este ponto.
A forma alternativa para o tal do findViewById é utilizar o Data Binding Library.
– Preparação
Para utilizar esta biblioteca, você deve ter o Android Studio na versão 1.5 ou superior… o que não deve ser difícil, visto que a versão mais nova (hoje, dia 25/07/2017) é a 2.3.3.
Passo 1: Editar o build.gradle.
No seu projeto, geralmente você tem duas “pastas”: app e Gradle Scripts.
Clique em Gradle Scripts e abra o arquivo build.gradle (Module: app). Ele contém uma série de informações, cuidado para não estragar o projeto todo.
Neste arquivo, você vai adicionar o conteúdo abaixo dentro da seção android, conforme o exemplo:
android {
dataBinding {
enagled true
}
....outros conteudos
}
Você não deve apagar ou alterar outras linhas (a menos que realmente saiba o que está fazendo), apenas adicionar a linha mencionada. Após salvar, a IDE pedirá para sincronizar as alterações do arquivo com o projeto.
Clique em Sync Now para sincronizar e aguarde concluir.
Passo 2: Altere o layout
Todos os layouts que forem se beneficiar do data binding precisarão ser adaptados. Esta adaptação é bem simples.
Abaixo está um layout, conforme criado pelo Android Studio para a MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!" />
</RelativeLayout>
O que precisamos fazer no layout é: Encapsular o RelativeLayout em uma tag chamada layout e passar para ela os elementos XMLNS (XML NameSpaces). Veja abaixo como ficaria o layout do nosso exemplo:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<RelativeLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tvHello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!" />
</RelativeLayout>
</layout>
Passo 3: Faça um build no seu projeto.
Esta ação não é complicada, mas deixei em um passo separado, pois, o Data Binding precisa de alguns arquivos que são gerados automaticamente por esta ação.
Passo 4: Alterando a classe (.java)
Abra a sua classe MainActivity.java. Ela deve estar com um conteúdo parecido com este:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Agora vamos altera a classe, removendo o comando setContentView(R.layout.activity_main) e incluindo o necessário para o DataBinding funcionar.
Abaixo está o código adaptado…
public class MainActivity extends Activity {
//É este cara que vai guardar a referencia para tudo do seu layout.
ActivityMainBinding conteudo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Inicializando o nosso conteúdo.
conteudo = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
}
Uma explicação rápida: A classe ActivityMainBinding não foi criada explicitamente, mas a alteração que fizemos nos passos anterior preparou o terreno para a biblioteca do Data Binding cria-la automaticamente durante o build. Ela possui referencia para tudo que você incluir no seu layout. Similar a classe R, esta é mantida automaticamente pela IDE, ou seja, você não precisa alterá-la manualmente… e por não precisa eu quero dizer: não altere esta classe na mão, a menos que você queria estragar seu projeto.
O nome para a classe é o nome da sua activity com as primeiras letras em maiúsculo e o sufixo Binding. Exemplo: activity_main.xml gerou o arquivo ActivityMainBinding. Esta lógica é aplicada em todas as classes que você quiser utilizar o Data Binding.
Esqueci de mencionar, mas já terminamos de configurar. Para utilizar os elementos do seu layout, basta chama-los como propriedade da variável do tipo ActivityMainBinding chamada conteudo.
No nosso layout de exemplo, temos apenas o elemento TextView com o ID tvHello. Para alterar o seu texto basta utilizar o comando:
conteudo.tvHello.setText("Novo texto!");
De forma similar, você acessará outros elementos que incluir no layout.
No exemplo utilizado neste tutorial, temos apenas um elemento no layout. Então este processo pode parecer um pouco exagerado, mas pense em um layout com dezenas de controles…. dezenas de declarações de variáveis e de chamadas para o findViewById… Nestes casos, o Data Binding vai salvar muito tempo.
Acredito que aqui cabe uma breve explicação sobre como a biblioteca do Data Binding gera as propriedades dentro da classe gerada automaticamente (no nosso caso, a ActivityMainBinding): Os nomes das propriedades são gerados com o padrão camelCase e tem os caracteres especiais removidos, ou seja, se você criar um TextView com o id @+id/tv_Login, a propriedade gerada será tvLogin (sem o underscore e com camelCase).
Extra!
Existem algumas bibliotecas que conseguem reduzir ainda mais o tempo de desenvolvimento. A Butter Knife, por exemplo, utiliza annotations para simplificar o binding.
Para fazer o binding com ela, bastaria utilizar o exemplo abaixo:
class MainActivity extends Activity {
@BindView(R.id.tvHello) TextView tvHello;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
}
}
Qual a melhor opção? Boa pergunta. Depende do seu projeto, mas qualquer coisa que evite ter que utilizar o findViewById infinitas vezes é uma boa opção.
Espero ter ajudado. Bom desenvolvimento! 🙂