androidkotlinmvvmviewmodelandroid-livedata

Android LiveData observe not triggered by postValue()


When my app closes I want to perform some simple post-processing in processResponse(...) in ActivityBase after signing out from Firebase Auth. It actually signs out but this post-processing in processResponse(...) after app is closed is not called. I am writting my app in compliance with MVVM (though I am new to this).

Here is my the most important code regarding this issue:

class UserServiceSignOutImpl : UserServiceSignOut, AuthStateChangeProcessing {
    private val auth = FirebaseAuth.getInstance()

    override fun signOut(): Observable<AuthListener> {
        return Observable.create { emitter: ObservableEmitter<AuthListener> ->
            MyAuthStateListener(auth).getAuthStateListener(emitter, this)
        }
    }

    override fun onProcessing(emitter: ObservableEmitter<AuthListener>) {
        emitter.onNext(AuthListener.success("Logged out successfully."))
    }
}
class ViewModelBase : ViewModel() {
    val authListener: MutableLiveData<AuthListener> = MutableLiveData()
    private val userServiceSignOut: UserServiceSignOut = UserServiceSignOutImpl()

    companion object {

        private lateinit var instance: ViewModelBase

        @MainThread
        fun getInstance(): ViewModelBase {
            instance = if (::instance.isInitialized) instance else ViewModelBase()
            return instance
        }

    }

    fun signOut() {
        userServiceSignOut.signOut().subscribe(object : Observer<AuthListener> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(_authListener: AuthListener) {
                authListener.postValue(_authListener)
            }

            override fun onError(e: Throwable) {
                authListener.postValue(error(e.message!!))
            }

            override fun onComplete() {
            }
        })
    }
}
class MyApp : Application(), ActivityLifecycleCallbacks {

    private var activityCounter = 0

    override fun onCreate() {
        super.onCreate()

        registerActivityLifecycleCallbacks(this)
    }

    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}

    override fun onActivityStarted(activity: Activity) {
        activityCounter++
    }

    override fun onActivityResumed(activity: Activity) {}

    override fun onActivityPaused(activity: Activity) {}

    override fun onActivityStopped(activity: Activity) {
        activityCounter--
        if (activityCounter == 0) {
            (activity as ActivityBase).viewModel.signOut()
        }
    }

    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

    override fun onActivityDestroyed(activity: Activity) {}
}
abstract class ActivityBase : AppCompatActivity() {

    lateinit var viewModel: ViewModelBase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = ViewModelBase.getInstance()
        viewModel.authListener.observe(this) { authListener: AuthListener -> processResponse(authListener) }
    }
    
    private fun processResponse(authListener: AuthListener) {
        when (authListener.status) {
            AuthListener.Status.SUCCESS -> {
                Toast.makeText(this, "You have been logged out successfully.", Toast.LENGTH_SHORT).show()
            }

            AuthListener.Status.ERROR -> {
                Toast.makeText(this, "There was a problem", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

Solution

  • Solved! It turned out I need to change viewModel.authListener.observe(...) to viewModel.authListener.observeForever and after that I need to manually stop observing this with viewModel.authListener.removeObservers(...)