'Problem of automatically observing login state using Firebase

I am using the Navination Component to switch the screen and implementing the login state using Firebase.

The flow of the app is as follows :

Run the app -> CalendarFragment (startDestination) -> Check if signed in -> Go to LogInFragment if not signed in -> sign in -> Go to CalendarFragment

The problem here is when i move to LogInFragment after checking the login.

If i go to LogInFragment, observe in viewmodel will run UNAUTHENTICATED flow.

I made the observe use of the viewmodel to inspect the state when the login button is pressed.

I don't want to automatically check when I go to the Log In screen.

What is the cause and how do I fix it?


Repository

class AuthenticationRepository {
    private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()
    private val userLiveData: MutableLiveData<FirebaseUser?> = MutableLiveData<FirebaseUser?>()
 
    fun getUserData() : MutableLiveData<FirebaseUser?> {
        userLiveData.postValue(firebaseAuth.currentUser)
        // Once logged in, the Firebase user value remains, 
        // so the status continues to be AUTHENTICATED. So temporarily set null value.
        userLiveData.postValue(null)
        return userLiveData
    }
    fun login(email: String, pwd: String) {
        firebaseAuth.signInWithEmailAndPassword(email, pwd)
            .addOnCompleteListener { task ->
                if(task.isSuccessful) { // log in succuss
                    userLiveData.postValue(firebaseAuth.currentUser)
                }
                else {
 
                } // Failed
            }
    }
}

ViewModel

class LoginViewModel : ViewModel() {
    private val repository: AuthenticationRepository = AuthenticationRepository()
    val authenticationState = repository.getUserData().map { user ->
        if (user != null) {
            AuthenticationState.AUTHENTICATED
        } else {
            AuthenticationState.UNAUTHENTICATED
        }
    }
 
    sealed class AuthenticationState {
        object AUTHENTICATED: AuthenticationState()
        object UNAUTHENTICATED : AuthenticationState()
    }
     
    fun login(email: String, pwd: String) : LiveData<AuthenticationState> {
        repository.login(email, pwd)
        return authenticationState
    }
}

CalendarFragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
 
        loginVM.authenticationState.observe(viewLifecycleOwner) { authState ->
            when(authState) {
                LoginViewModel.AuthenticationState.AUTHENTICATED ->
                    Toast.makeText(context, "Logged In",Toast.LENGTH_SHORT).show()
                else -> {
                    Toast.makeText(context, "Not Logged In",Toast.LENGTH_SHORT).show()
                    findNavController().navigate(R.id.login_nav)
                }
            }
        }
    }

LoginFragment


override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
     
    binding.btnLogin.setOnClickListener { _ ->
        login()
    }
}
 
private fun login() {
    // Request Log In
    var email: String = binding.etId.text.toString()
    var pwd: String = binding.etPwd.text.toString()
 
    loginVM.login(email, pwd).observe(viewLifecycleOwner) { test ->
        when(test) {
            LoginViewModel.AuthenticationState.AUTHENTICATED -> {
                findNavController().popBackStack()
                Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show()
            }
            LoginViewModel.AuthenticationState.UNAUTHENTICATED ->
                Toast.makeText(context, "Failed", Toast.LENGTH_SHORT).show()
        }
    }
}

Note: Both CalendarFragment and LoginFragment use LogInViewModel and use activityViewModels()



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source