Android Jetpack — ViewModel primeiros passos.
O artigo de hoje será sobre o componente ViewModel do Android Jetpack.
Utilizando ViewModel em nossas aplicações ganhamos a capacidade de armazenar informações e objetos customizados que sobrevivam aos eventos de rotação e do ciclo de vida Android.
Em resumo, o componente ViewModel é um componente inteligente que é capaz de sobreviver ao processo de recriação de Activities. Se você é iniciante do mundo de desenvolvimento Android saiba que, ao rotacionar a tela dos dispostivos o sistema operacional destroi toda a instância da Activity e a recria de acordo com as novas configurações do sistema, e isso implica em inflar novamente o layout adequado quando existir, configurações de estilos e ou outros padrões de UI como o Master-Detail-Flow.
A capacidade de resistir a tais mudanças se deve ao fato do componente ter conhecimento do ciclo de vida da UI como Activities e Fragments, e por consequência o ViewModel é um componente chamado de Life-cycle-aware do Android Jetpack por ter essa capacidade.
Em muitas situações o ViewModel é usado em conjunto com outra bilioteca que também é Life-cycle-aware chamada LiveData. Contudo, para manter esse artigo simples e de fácil compreenção, iremos restringir o escopo do artigo ao componente ViewModel.
Como podemos ver acima, a idéia do ViewModel é fazer com que nossa UI tenha apenas como objetivo renderizar e apresentar informações ao usuário, seguindo o princípio da responsabilidade única — SOLID. Assim, os dados da nossa aplicação estão armazenados na ViewModel que os expõem de maneira cautelosa e sempre de acordo com o ciclo de vida correto da aplicação.
As principais vantagens de utilizar o ViewModel são:
- Simplificação e redução de boiler-plate code dentro de Activities e Fragments.
- Capacidade de isolar os dados utilizados pela UI (Activity, Fragments) e fazê-los sobreviver ao ciclo de vida da aplicação.
- Aplicação de padrões de arquitetura e design patterns como o SOLID. (i.e Single Responsability Principle)
- Integração com demais componentes de arquitetura como LiveData, Room e afins.
Introdução ao Projeto: ViewModel + Fragments
Neste artigo, iremos desenvolver um projeto que usa dois Fragmentos para manter um estado de um contador, e para isso precisaremos de dois botões que tenham a capacidade de incrementar e ou reduzir o estado do contador.
Veja o projeto a seguir:
Repare que ao rotacionar a tela o estado do contador é zerado e perdemos o nosso progresso. Com a implementação do ViewModel iremos manter o estado do contador independentemente do ciclo de vida, e assim mesmo que a Activity seja destruída nossa informação será salva.
1ª Passo — Criação do Projeto, Fragmentos e Layout
Android Studio -> File -> New -> New Project -> Next -> Finish
Agora com o novo projeto criado, vá até o layout “activity_mail.xml” e o configure conforme a seguir:
O layout acima tem como objetivo dividir a tela com dois fragmentos que iremos construir a seguir.
Antes de partimos para criação dos fragments de fato, iremos criar um layout único que será o mesmo para os dois fragmentos — UI.
O layout terá apenas dois botões para aumentar ou diminuir o contador no centro da tela, e um texto que indica o estado do contador no centro de cada Fragmento. Veja o exemplo a seguir.
Código Fonte do Layout dos Fragmentos:
Agora com o layout pronto, vamos criar dois fragmentos que irão incrementar e ou diminuir o contador na tela ao clicar nos botões correspondentes.
Para isto, vamos criar uma nova classe que implemente os métodos necessários da classe Fragment da biblioteca de suporte do Google.
Confira a implementação de nossos fragments. Lembrando que devemos criar dois para implementar nosso projeto.
Código fonte do primeiro fragmento.
No Fragment acima, repare que temos uma variável global do tipo Int chamada counterNumber que irá armazenar o número do contador.
Temos dois métodos, onCreateView e o onViewCreated. O primeiro cuida de inflar o layout da tela do Fragmento e o segundo é executado após o layout ser inflado e renderizado na aplicação.
O código a seguir é um padrão muito comum no desenvolvimento Android. É aqui que configuramos a nossa ação ao clicar nos botões correspondentes.
Sempre que alguém pressionar o botão aumentar o bloco a seguir é executado.
O mesmo acontece para o botão diminuir do Fragment.
Código fonte do segundo fragmento.
Agora que temos nossos dois fragmentos criados em nosso projeto, podemos modificar o nosso layout principal “activity_main.xml” para inflar os fragmentos correspondentes via XML.
Para isso, basta adicionar o atributo “name” com o nome do pacote e classe no layout para que o Android faça o resto para nós.
2ª Passo — Configuração das dependências.
As dependências do Android Jetpack podem ser encontradas aqui.
Para este artigo, apenas as seguintes dependências são necessárias.
dependencies {
... def lifecycle_version = "1.1.1" implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
kapt "android.arch.lifecycle:compiler:$lifecycle_version"implementation "android.arch.lifecycle:extensions:$lifecycle_version"
}
3ª Passo — Implementando a ViewModel
Em nosso último passo, precisamos implementar nossa ViewModel de fato que irá reter e guardar as informações que nossos fragmentos usam para exibir o estado do contador na tela do usuário.
Para isso, basta herdar da classe ViewModel e declarar os objetos e variáveis que precisamos reter durante o ciclo de vida da aplicação.
Em futuros artigos, iremos extender a funciondalidade da ViewModel para implementar outros componentes como LiveData e os padrões de arquitetura Repositório.
Graças ao Kotlin, não precisamos declarar nenhuma função Getter/Setter pois elas são implicitamente declaradas e implementadas pelo compilador.
Usando a ViewModel nos Fragmentos.
Agora que nossa classe ViewModel está preparada para uso, podemos utilizar um ViewModelProvider da biblioteca para criar e instanciar nossa classe.
Para isso, basta declarar uma linha de código conforme a seguir:
//Criação de uma ViewModel usando um ViewModelProvider
val viewModel = ViewModelProviders.of(this).get(CounterViewModel::class.java)
A palavra this no código acima possui um significado importante. This precisa ser necessariamente um objeto que tenha um ciclo de vida, e que implementem a interface Life-cycle owner. Fragmentos e Activities a partir da versão 26.1 da Support Library já implementam corretamente as interfaces necessárias para que o ViewModel funcione corretamente.
Com isso, podemos modificar o código de nossos fragmentos para usar e setar o estado do contador conforme a seguir.
Dessa forma, nossos fragmentos estão apenas consumindo o estado do contador que fica armazenado diretamente na ViewModel e assim mesmo que nossa Activity seja destruída os dados estarão sendo persistidos em tempo de execução.
Veja como nosso projeto agora com o poder do ViewModel guarda o estado do Contador.
Conclusão
A implementação do componente ViewModel neste artigo é sem dúvidas muito simples, mas o objetivo aqui foi demonstrar a capacidade dessa nova biblioteca do Android Jetpack ajudar no processo de gerenciamento do estado e do ciclo de vida de uma aplicação Android.
Em futuros artigos iremos explorar diferentes formas de combinação com outros componentes do Jetpack que são Life-cycle-aware.
Fique ligado!
Abraços.