Como compartilhar ViewModel KMM?
Entenda como compartilhar ViewModel entre iOS e Android em um projeto Kotlin Multiplatform Mobile (KMM)
Por que compartilhar o ViewModel?
Os motivos mais importantes são:
Melhorar a manutenibilidade
Reduzir custos de desenvolvimento
Não duplicar código
Reduzir o tempo de desenvolvimento
Reduzir a quantidade de código e testes
Ter um código mais coeso e evitar efeitos colaterais. (quando algo funciona em uma plataforma mas não na outra e vice-versa)
Como compartilhamos o viewModel em KMM?
Em um mundo ideial, o ViewModel existirá apenas no módulo comum (CommonMain/Shared - veja imagem 1). Porém, como a plataforma Android nos oferece uma série de benefícios com sua própria implementação classe de ViewModel, tais como: viewModelScope (Coroutine) e controle de ciclo de vida, torna-se interessante re-usar o máximo desta lógica, para não re-inventar a roda.
No entando, queremos ter uma interface comum entre ambas as plataformas iOS e Android, KMM nos oferece um mecanismo conhecido como expect/actual, que veremos a seguir.
Mecanismos de Compartilhamento de Código
Como podemos ver na imagem 2, KMM nos oferece duas maneiras de compartilhar código, uma usando as keywords (palavras reservadas) expect/actual ou definindo interfaces nativas em kotlin. A ideia por trás é sempre a mesma, oferecer um ponto comum para ambas as plataformas.
Expect/Actual vs Interfaces
Quando favoreço um ou outro?
Essa é uma boa pergunta. Tanto a comunidade como o próprio pessoal da Jetbrains não são precisos em suas colocações, mas deixam a entender o seguinte:
Expect/Actual: Ótimo para resolver dependências estáticas, valores primitivos ou até mesmo classes/interface. Como veremos no exemplo a seguir do ViewModel. A Jetbrains recomenda que deveriámos favorecer Expect/Actual ao invés de interfaces sempre que possível.
Interfaces: São mais flexíveis e mais fáceis de testar. Eu optaria por interfaces onde houver cenários que precise implementar vários métodos nátivos da plataforma e/ou desejar ter mais flexibilidade nos testes, ou no caso que eu precisasse usar algo já disponível em alguma implementação do expect/actual. Mas sendo bem sincero, ainda não tenho uma opinião 100% formada e acredito que aqui não exista realmente um “certo ou errado”.
Implementação referência
BaseSharedViewModel
Basicamente o que precisamos aqui é definir uma classe base na plataforma dentro do módulo commonMain da seguinte maneira (note que estou usando a keyword expect):
expect abstract class BaseSharedViewModel() {
val scope: CoroutineScope
protected fun onCleared()
}
iOSMain & androidMain
Nas respectivas plataformas, implementamos cada uma de acordo com as caracteristicas da plataforma. Diferentemente da definição, aqui usamos a keyword actual.
iOSMain
actual abstract class BaseSharedViewModel {
actual val scope: CoroutineScope = MainScope()
protected actual open fun onCleared() {
// outras coisa que deseje limpar
}
fun clear() {
onCleared()
scope.cancel()
}
}
androidMain
actual abstract class BaseSharedViewModel: ViewModel() {
actual val scope = viewModelScope
actual override fun onCleared() {
super.onCleared()
}
}
abstract class
como são classes base, defini elas como abstract. Assim a implementação concreta poderá herdar dela e KMM se encarrega, na hora de gerar os binários, de empacotar a classe referente a cada plataforma.
Acesso nativo
XyzViewModel (implementações concretas)
Xyz representa o prefixo do modelo concreto. As implementações podem então acontecer de forma centralizada no commonMain (shared) e as plataformas fazem acesso aos modelos através de um único ponto comum. Segue exemplo:
class SampleViewModel : BaseSharedViewModel() {
// Your business logic and states goes here...
}
Você precisa compartilhar o ViewModel no seu projeto KMM?
Veja na prática como se faz!
Agora que você já sabe como esboçar e visualizar o compartilhamento, veja como criar o código necessário em kotlin, para resolver essa tarefa em um projeto real kotlin multiplatform mobile, com tudo que é necessário (dependências, imports, estrutura de pacotes etc.) Neste vídeo, te explico todo o passo-a-passo:
Quer mais conteúdo assim?
Me siga, se você gosta desse tipo de conteúdo técnico didático e feito com muito carinho. ❤️
Você me encontra no 🐦twitter, 🦑 Github ou no 📺 Youtube onde tenho um curso gratuito “Do zero ao certificado Android”, outro chamado “Resoluções a problemas comuns Android” e Android Jetpack Compose disponíveis 0800 para você.
Para não perder nenhum conteúdo, inscreva-se nesse techblog clicando aqui: