Conceitos e implementação do Jetpack Compose
Nesta página, apresentamos várias práticas recomendadas e sugestões para a arquitetura. Adote nossas dicas para melhorar a qualidade, robustez e escalonabilidade do app. Elas também facilitam os processos de manutenção e teste do app.
Camada de IU
A função da camada de IU é mostrar os dados do app na tela e atuar como o ponto principal de interação do usuário. Confira algumas práticas recomendadas para a camada de IU:
- Crie repositórios, mesmo que eles contenham somente uma fonte de dados.
- Em apps pequenos, é possível colocar tipos de camada de dados em um pacote ou módulo de
data.
Recomendação |
Descrição |
Seguir o fluxo de dados unidirecional (UDF, na sigla em inglês). Altamente recomendável |
Siga os princípios do fluxo de dados unidirecional (UDF), em que os ViewModels expõem o estado da interface usando o padrão de observador e recebem ações da interface por chamadas de método. |
Usar os ViewModels do AAC, caso sejam vantajosos para o app. Altamente recomendável |
Use ViewModels do AAC para processar a lógica de negócios e busque dados do app para expor o estado da interface à interface. Confira mais práticas recomendadas do ViewModel. Confira os benefícios dos ViewModels. |
Usar a coleta de estado da IU com reconhecimento de ciclo de vida. Altamente recomendável |
Colete o estado da interface usando o builder adequado de corrotinas com reconhecimento de ciclo de vida, Leia mais sobre |
Não enviar eventos do ViewModel para a IU. Altamente recomendável |
Processe o evento imediatamente no ViewModel e cause uma atualização de estado com o resultado. Saiba mais sobre os eventos de IU. |
Usar um aplicativo de atividade única. Recomendado |
Use fragmentos de navegação para alternar entre as diferentes telas e links diretos para o app, caso ele tenha mais de uma tela. |
O snippet abaixo descreve como coletar o estado da IU de uma forma que reconhece o ciclo de vida:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
// Process item
}
}
}
}
}
ViewModel
Os ViewModels são responsáveis por fornecer o estado da IU e o acesso à camada de dados. Confira algumas práticas recomendadas para ViewModels:
Recomendação |
Descrição |
Os ViewModels precisam ser independentes do ciclo de vida do Android. Altamente recomendável |
Os ViewModels não podem conter uma referência a nenhum tipo relacionado ao ciclo de vida. Não transmita |
Usar corrotinas e fluxos. Altamente recomendável |
O ViewModel interage com as camadas de dados ou de domínio usando:
|
Usar ViewModels na tela. Altamente recomendável |
Não use ViewModels em partes reutilizáveis da IU. Em vez disso, use-os em:
|
Não use Altamente recomendável |
Use a classe |
Expor um estado da IU. Recomendado |
Os ViewModels precisam expor dados à IU usando uma única propriedade conhecida como
|
O snippet abaixo demonstra como expor o estado da IU de um ViewModel:
@HiltViewModel
class BookmarksViewModel @Inject constructor(
newsRepository: NewsRepository
) : ViewModel() {
val feedState: StateFlow<NewsFeedUiState> =
newsRepository
.getNewsResourcesStream()
.mapToFeedState(savedNewsResourcesState)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = NewsFeedUiState.Loading
)
// ...
}
Ciclo de vida
Apresentamos abaixo algumas práticas recomendadas para trabalhar com o ciclo de vida do Android:
Recomendação |
Descrição |
Não substitua métodos de ciclo de vida em atividades ou fragmentos. Altamente recomendável |
Não substitua os métodos de ciclo de vida, como |
O snippet abaixo descreve como executar operações de acordo com um determinado estado do ciclo de vida:
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
// ...
}
override fun onPause(owner: LifecycleOwner) {
// ...
}
}
}
}