Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional
Instruções Gerais:
- Resolva as atividades em ordem progressiva de maturidade.
- Cada nível adiciona requisitos técnicos, tratamento de erros e casos de borda reais.
- Consulte o gabarito comentado ao final de cada questão para autoavaliação.
🎯 Nível 1: Fundamentos
Problema 10.1 — ViewModel com StateFlow para Emissão de Estado
Contexto: ViewModel com StateFlow para Emissão de Estado no contexto de Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional.
Requisitos de Execução:
- Criar
ContadorViewModelherdando deViewModelexpondoStateFlow<Int>imutável.
Resultado Esperado
ViewModel gerenciando estado com StateFlow e sobrevivência à recriação.
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_10_1_SeuNome - Envie na tarefa:
Atividade Cap 10 - Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.viewmodel
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class ContadorViewModel : ViewModel() {
private val _contador = MutableStateFlow(0)
val contador: StateFlow<Int> = _contador.asStateFlow()
fun incrementar() {
_contador.value += 1
}
}
🔍 Nível 2: Prática
Problema 10.2 — Coleta Segura de Estado no Compose com collectAsStateWithLifecycle()
Contexto: Coleta Segura de Estado no Compose com collectAsStateWithLifecycle() no contexto de Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional.
Requisitos de Execução:
- Consumir StateFlow do ViewModel no
@Composablerespeitando o ciclo de vida do Android.
Resultado Esperado
UI Compose atualizada reativamente conforme o ciclo de vida.
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_10_2_SeuNome - Envie na tarefa:
Atividade Cap 10 - Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.ui
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.empresa.mobile.viewmodel.ContadorViewModel
@Composable
fun TelaContador(viewModel: ContadorViewModel) {
val count by viewModel.contador.collectAsStateWithLifecycle()
Text("Valor atual emitido pelo ViewModel: $count")
}
⚡ Nível 3: Integração
Problema 10.3 — Padrão MVI com Intents/Events e Reducer de Estado
Contexto: Padrão MVI com Intents/Events e Reducer de Estado no contexto de Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional.
Requisitos de Execução:
- Modelar sealed interface
PerfilIntente processar eventos unificados no ViewModel.
Resultado Esperado
Arquitetura MVI (Model-View-Intent) garantindo rastreabilidade de eventos.
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_10_3_SeuNome - Envie na tarefa:
Atividade Cap 10 - Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.viewmodel
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
sealed interface PerfilIntent {
data class AlterarNome(val novoNome: String) : PerfilIntent
data object Salvar : PerfilIntent
}
class PerfilMviViewModel : ViewModel() {
private val _estado = MutableStateFlow("Inicial")
val estado = _estado.asStateFlow()
fun onIntent(intent: PerfilIntent) = when (intent) {
is PerfilIntent.AlterarNome -> _estado.value = "Editando: ${intent.novoNome}"
PerfilIntent.Salvar -> _estado.value = "Salvo com sucesso"
}
}
🏆 Nível 4: Desafio Corporativo
Problema 10.4 — Tratamento de One-Off Events (Side Effects) com Channel e SharedFlow
Contexto: Tratamento de One-Off Events (Side Effects) com Channel e SharedFlow no contexto de Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional.
Requisitos de Execução:
- Emitir eventos únicos como
ExibirToastouNavegarParaLoginque não devem ser re-emitidos na rotação de tela.
Resultado Esperado
One-off events tratados com segurança sem duplicação de efeitos colaterais.
📤 Instruções de Entrega (Microsoft Teams)
- Salve o arquivo como:
Atividade_10_4_SeuNome - Envie na tarefa:
Atividade Cap 10 - Arquitetura MVVM/MVI com ViewModel, UiState e Fluxo Unidirecional
🔑 Gabarito de Código & Solução Comentada
package com.empresa.mobile.viewmodel
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
sealed interface UiEvent {
data class MostrarMensagem(val msg: String) : UiEvent
data object Navegar : UiEvent
}
class EventosViewModel : ViewModel() {
private val _eventos = Channel<UiEvent>(Channel.BUFFERED)
val eventos = _eventos.receiveAsFlow()
suspend fun dispararSucesso() {
_eventos.send(UiEvent.MostrarMensagem("Operacao corporativa realizada!"))
}
}
| ⬅️ Voltar ao Índice de Exercícios | 📚 Sumário de Tópicos |