简体   繁体   中英

Observer in Fragment works but not in Activity

I created an Observer in a Fragment which works perfectly (it fires a toast when an Int increases), but when I try to move this code into the Activity, the observer doesn't seem to connect and it does not update when the LiveData changes.

Fragment ( this works! ):

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

    loginViewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)

    loginViewModel.getLoginAttemptCount().observe(this, Observer { count ->
        if (count > 0) makeToast("Authentication failed")
    })
}

Activity ( when I put the observer in the Activity it doesn't! ):

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.login_activity)

    loginViewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)

    loginViewModel.getLoginAttemptCount().observe(this, Observer { count ->
        if (count > 0) makeToast("Authentication failed")
    })
}

ViewModel ( both call same function in VM ):

    fun getLoginAttemptCount(): MutableLiveData<Int> {
    Log.d(TAG, "getLoginAttemptCount()")
    return firestoreRepository.getLoginAttemptCount()  }

Repo ( called from VM ):

        fun getLoginAttemptCount(): MutableLiveData<Int>{
            Log.d(TAG, "getLoginAttemptCount()")
            return loginAttempt
    }

loginAttempt.value is increased everytime there is a login attempt and I have verified this works in Logcat..

For info, makeToast is simply a function to create a justified Toast (text and position):

private fun makeToast(message: String) {

    val centeredText: Spannable = SpannableString(message)
    centeredText.setSpan(
        AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER),
        0, message.length - 1,
        Spannable.SPAN_INCLUSIVE_INCLUSIVE
    )

    val toast = Toast.makeText(this, centeredText, Toast.LENGTH_LONG)
    toast.setGravity(Gravity.CENTER,0,0)
    toast.show()
    Log.d(TAG, "Toast message: $message")
}

I'm assuming it is to do with the lifeCycleOwner but I am at a loss!

loginViewModel = ViewModelProviders.of(this).get(LoginViewModel::class.java)

In Fragment you are using above line to create loginviewmodel passing the context of fragment to viewmodel so,the first thing android does is that it check,if it contain's any other viewmodel associated with this fragment, if it contains it will not create new Viewmodel it will return the old one if it does not contain it create a new one.Viewmodel are created using key value pair. So in your case you are creating total two viewmodel each of fragment and activity you are changing the live data of fragment but you are trying to observe it in activity using activity viewmodel. If you want to acheive that you need to create shared viewmodel among activity and fragment. How to create shared viewmodel

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM