'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 toLogInFragmentif not signed in -> sign in -> Go toCalendarFragment
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 |
|---|
