8. Programando Login com Firebase

8.2. Classe LoginFragment

O fragmento de tela de Login é responsável por receber as credenciais do usuário e encaminhar a autenticação para o serviço do Firebase. Na implementação deste código, vamos usar um recurso avançado, chamado View Binding (Vinculação de Visualização), que facilita a manipulação dos componentes da interface de um fragmento ou atividade. Além disso, a autenticação no Firebase será realizada de forma assíncrona, permitindo uma experiência fluida ao usuário ao processar as respostas sem bloquear a interface.

Vinculação de Visualização (View Binding)

View Binding é uma funcionalidade do Android que simplifica o acesso aos elementos da interface definidos em XML. Com ele, não precisamos mais utilizar findViewById para acessar cada componente, evitando erros de null e aumentando a segurança do código. Para habilitar View Binding, basta ativá-lo no arquivo build.gradle do projeto. A partir daí, o Android Studio gera automaticamente uma classe de vinculação para cada layout XML, cujo nome segue o padrão NomeDoArquivoLayoutBinding. No fragmento de login, ao invés de acessar diretamente os elementos da interface, faremos referência a eles por meio da classe de vinculação, proporcionando uma navegação e manipulação mais segura e organizada dos elementos.

Como usamos a template Basic Views Activity neste projeto, a função view-binding já está ativa e podemos pular direito para a programação do fragmento.

Programação Assíncrona com Firebase

Ao usar o Firebase para login, o processo ocorre de forma assíncrona para que o aplicativo continue respondendo aos toques e ações do usuário. A programação assíncrona em Android usa listeners (ouvintes) que monitoram a conclusão de uma tarefa. No Firebase, métodos como signInWithEmailAndPassword retornam uma tarefa assíncrona e permitem adicionar ouvintes com o método addOnCompleteListener. Esse ouvinte verifica quando o processo é concluído e, dependendo do sucesso ou falha da operação, toma as ações apropriadas — como redirecionar o usuário para a tela principal ou exibir uma mensagem de erro.

Este fluxo assíncrono é essencial, pois evita que a interface gráfica congele durante a autenticação, garantindo uma experiência de usuário suave.

Abaixo, segue o código completo:

package ...

import ...

class LoginFragment : Fragment() {
//binding das views automatizado
private var _binding: FragmentLoginBinding? = null
private val binding get() = _binding!!
//firebase
private lateinit var mAuth: FirebaseAuth //acessa os recursos de autenticação do Firebase

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("TODO2024","app ligou a login")
}

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//configura a vinculação
_binding = FragmentLoginBinding.inflate(inflater, container, false)
//adiciona uma ação ao botão de login
binding.loginButton.setOnClickListener {
fazerLogin()
}
//adiciona uma ação ao botão de ir para cadastro
binding.gotoCadastroButton.setOnClickListener{
findNavController(requireView()).navigate(R.id.action_loginFragment_to_cadastroFragment)
}
//inicializa firebase
mAuth = Firebase.auth
// Inflate the layout for this fragment
return binding.root
}

fun fazerLogin() {
val usuario = binding.emailInputLayout2.editText?.text.toString().trim()
val senha = binding.senhaInputLayout2.editText?.text.toString().trim()
mAuth.signInWithEmailAndPassword(usuario, senha)
//Método assíncrono para lidar com a resposta da solicitação
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d("TODO2024", "Login efetuado com sucesso indo para home")
findNavController(requireView()).popBackStack()
} else {
Log.w("TODO2024", "Falha ao fazer Login: ", task.exception)
}
}
}
}

Método onCreateView

O método onCreateView implementa a configuração inicial do view-binding na primeira linha. Após, o carregamento do arquivo FragmentLoginBinding o objeto binding vai conter todas as referências aos componentes da UI do arquivo de layout.

Com o objeto binding acessamos os dois botões da tela e adicionamos um evento para fazer o login e outro para encaminhar a tela de cadastro. Também inicializamos o objeto mAuth para uso posterior.

No retorno deve ser escrito binding.root o que equivale a chamar o método getRoot(), fornecendo uma referência da visualização raiz do arquivo de layout correspondente. Neste caso específico, o FrameLayout que criamos no arquivo fragment_login.xml.

Método fazerLogin

Vamos realizar a autenticação no Firebase utilizando e-mail e senha com o método signInWithEmailAndPassword do objeto mAuth. Esse método faz uma requisição à API do Firebase, e a resposta não é imediata; por isso, precisamos usar programação assíncrona para não bloquear a interface do usuário durante a autenticação.

O próprio Firebase oferece suporte para programação assíncrona. Podemos implementar facilmente um método para lidar com a resposta do evento addOnCompleteListener. Esse evento recebe um objeto task que contém o resultado da autenticação (AuthResult). Com ele, verificamos se a operação foi bem-sucedida usando um fluxo de decisão, que nos permite escolher a ação adequada para cada situação.

  • Em caso de sucesso: o usuário é direcionado de volta à tela inicial. Diferente da navegação para uma nova tela, onde informamos explicitamente uma transição, retornar à tela anterior é mais simples e pode ser feito com o método popBackStack do NavController.
  • Em caso de falha: registramos uma mensagem de log com o erro. Essas mensagens podem ser visualizadas no LogCat do Android Studio, uma ferramenta útil para diagnosticar problemas. Se o Firebase estiver mal configurado, a conexão de rede apresentar problemas ou houver algum outro erro, o log exibirá informações úteis para corrigir a questão.