1
resposta

[Dúvida] Tratamento do retorno do método autentica

No aula Autenticando usuário, nós implementamos a opção de autenticar o login de um usuário, e utilizados coroutines e flow para retornar o usuário e ao validar o id e senha ele abre a tela de listaProdutosActivity. O problema ocorre quando é efetuada uma troca de senha do usuário já logado, ele insere novamente a tela de listaProdutosActivity na pilha de telas, sobrepondo a mesma ou outra telas já abertas.

Qual solução eu posso adotar e qual a melhor forma de evitar esse tipo de ocorrência? Pelo meu pouco conhecimento acredito estar relacionado ao uso do flow que fica verificando se houve alguma alteração de dados, mas não sei dizer ao certo porque essa chamada de abertura ocorre na tela de LoginActivity. Quando a tela de ListaProdutosActivity abre não deveria ser interrompido o uso do flow por conta do ciclo de vida da activity em que ele foi chamado?

Abaixo segue o código de abertura da tela chamando o método de autentica e a query que é executada.

lifecycleScope.launch {
                usuarioDao.autentica(usuarioId, senha).collect { usuario ->
                    usuario?.let {
                        dataStore.edit { preferences ->
                            preferences[usuarioLogadoPreferences] = usuario.id
                            **vaiPara(ListaProdutosActivity::class.java)**
                        }
                    } 
                }
            }

@Query("SELECT * FROM Usuario WHERE id = :usuarioId AND senha = :senha")
fun autentica(usuarioId: String, senha: String): Flow<Usuario?>
1 resposta

Olá, Jônatas.

Tudo bem?

O problema parece estar relacionado ao comportamento do Flow e ao ciclo de vida das Activities. Quando a senha é alterada, o Flow continua emitindo valores e, consequentemente, a tela ListaProdutosActivity é aberta novamente, sobrepondo a tela atual.

Uma solução para evitar isso é garantir que a navegação para a ListaProdutosActivity ocorra apenas uma vez, ou seja, quando a autenticação é bem-sucedida pela primeira vez. Você pode usar um StateFlow ou SharedFlow para emitir o estado de autenticação e observar esse estado na LoginActivity.

Aqui está um exemplo de como você pode implementar isso:

  1. Crie um StateFlow para gerenciar o estado de autenticação:
class UsuarioViewModel : ViewModel() {
    private val _autenticacaoState = MutableStateFlow<Usuario?>(null)
    val autenticacaoState: StateFlow<Usuario?> = _autenticacaoState

    fun autentica(usuarioId: String, senha: String) {
        viewModelScope.launch {
            usuarioDao.autentica(usuarioId, senha).collect { usuario ->
                _autenticacaoState.value = usuario
            }
        }
    }
}
  1. Observe o StateFlow na LoginActivity e navegue para a ListaProdutosActivity apenas uma vez:
class LoginActivity : AppCompatActivity() {

    private val usuarioViewModel: UsuarioViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        lifecycleScope.launchWhenStarted {
            usuarioViewModel.autenticacaoState.collect { usuario ->
                usuario?.let {
                    dataStore.edit { preferences ->
                        preferences[usuarioLogadoPreferences] = usuario.id
                    }
                    vaiPara(ListaProdutosActivity::class.java)
                    // Resetar o estado para evitar múltiplas navegações
                    usuarioViewModel.resetAutenticacaoState()
                }
            }
        }

        // Chame o método de autenticação quando necessário
        usuarioViewModel.autentica(usuarioId, senha)
    }
}
  1. Adicione um método para resetar o estado de autenticação no UsuarioViewModel:
fun resetAutenticacaoState() {
    _autenticacaoState.value = null
}

Com essa abordagem, você garante que a navegação para a ListaProdutosActivity ocorra apenas uma vez após a autenticação bem-sucedida, evitando sobreposições indesejadas de telas.

Espero ter entendido e conseguido ajudar. Qualquer dúvida manda aqui. Bons estudos.