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:

  1. Criar ContadorViewModel herdando de ViewModel expondo StateFlow<Int> imutável.

Resultado Esperado

ViewModel gerenciando estado com StateFlow e sobrevivência à recriação.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_1_SeuNome
  2. 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:

  1. Consumir StateFlow do ViewModel no @Composable respeitando o ciclo de vida do Android.

Resultado Esperado

UI Compose atualizada reativamente conforme o ciclo de vida.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_2_SeuNome
  2. 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:

  1. Modelar sealed interface PerfilIntent e processar eventos unificados no ViewModel.

Resultado Esperado

Arquitetura MVI (Model-View-Intent) garantindo rastreabilidade de eventos.

📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_10_3_SeuNome
  2. 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:

  1. Emitir eventos únicos como ExibirToast ou NavegarParaLogin que 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)

  1. Salve o arquivo como: Atividade_10_4_SeuNome
  2. 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