I have a View Model named “subsViewModel” that I’m storing subscription details for use by various fragments and MainActivity.kt. When a user authenticates with Google Firebase authentication, I want to store the user’s details into subsViewModel as shown below:
Authenticate, Store Firebase User Information
// Authenticate users: auth = Firebase.auth if (auth.currentUser == null){ // Not Signed in, launch the signin utility: Log.d(TAG, "USERID: Not signed In, switching to SignInActivity") startActivity(Intent(this, SignInActivity::class.java)) finish() return } else { // store user information into the subscriptionViewModel: Log.d(TAG, "USERID: Already Authed. current: ${auth.currentUser} uid ${auth.currentUser?.uid}") subsViewModel.userID.postValue(auth.currentUser?.uid) subsViewModel.userEmail.postValue(auth.currentUser?.email) subsViewModel.userName.postValue(auth.currentUser?.displayName) Log.d(TAG, "USERID: PostPosted ${subsViewModel.userID.value}") }
I’ve found that while postValue() works great from a background thread, it does not work for my purposes from MainActivity.kt, as shown in this logcat:
Logcat output showing the current value of subsViewModel.userId after postValue()
2022-04-18 13:28:22.039 27736-27736/com.jonmacpherson.newspathfinder D/MainActivity: USERID: Already Authed. current: com.google.firebase.auth.internal.zzx@bd58250 uid **************************
2022-04-18 13:28:22.067 27736-27736/com.jonmacpherson.newspathfinder D/MainActivity: USERID: PostPosted
As you can see in the logcat above, there is no userId after the value was already set. This has to do with postValue() running on a different thread and being called out of order from the code above. So, while postValue() would eventually set the value correctly, it’s too late for my use.
How to fix:
Use setValue() from the main thread only. If you are unaware of what thread you are working from, chances are it’s the main thread.
StackOverflow about setValue() & postValue()
Fixed Code:
// Authenticate users: auth = Firebase.auth if (auth.currentUser == null){ // Not Signed in, launch the signin utility: startActivity(Intent(this, SignInActivity::class.java)) finish() return } else { // store user information into the subscriptionViewModel: subsViewModel.userID.setValue(auth.currentUser?.uid) subsViewModel.userEmail.setValue(auth.currentUser?.email) subsViewModel.userName.setValue(auth.currentUser?.displayName) }
Note: All code is a work in progress. This is the code I’m working on, and it’s posted as I run into errors. This work is not suitable for reuse, and no guarantees are offered to its suitability for any function. If you do find something of interest, feel free to reuse it in whole or part.