首页 > 解决方案 > ViewModel 和 LiveData 不会立即从 Firebase 实时数据库中获取更改

问题描述

为了从我的 Firebase 实时数据库中读取数据,我同时使用 aLiveDataViewModel.

LiveData

class FirebaseQueryLiveData(ref: DatabaseReference) : LiveData<DataSnapshot>() {
    private val query: Query = ref
    private val listener: MyValueEventListener = MyValueEventListener()
    private var listenerRemovePending = false

    private val removeListener = object : Runnable {
        override fun run() {
            query.removeEventListener(listener)
            listenerRemovePending = false
        }
    }

    override fun onActive() {
        super.onActive()
        if (listenerRemovePending) {
            Handler(Looper.getMainLooper()).removeCallbacks(removeListener)
        } else {
            query.addValueEventListener(listener)
        }
        listenerRemovePending = false
    }

    override fun onInactive() {
        super.onInactive()
        Handler(Looper.getMainLooper()).postDelayed(removeListener, 2000)
        query.removeEventListener(listener)
    }

    private inner class MyValueEventListener : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            value = snapshot
        }

        override fun onCancelled(error: DatabaseError) {
            return
        }
    }
}

ViewModel

class UsersViewModel : ViewModel() {
    private val uid = Firebase.auth.currentUser!!.uid
    private val USERS_REF: DatabaseReference = FirebaseDatabase.getInstance().getReference("/users/$uid")
    private val liveData: FirebaseQueryLiveData = FirebaseQueryLiveData(USERS_REF)
    private val usersLiveData: MediatorLiveData<Users> = MediatorLiveData()

    init {
        usersLiveData.addSource(liveData, object : Observer<DataSnapshot> {
            override fun onChanged(dataSnapshot: DataSnapshot?) {
                if (dataSnapshot != null) {
                    usersLiveData.postValue(dataSnapshot.getValue(Users::class.java))
                } else {
                    usersLiveData.value = null
                }
            }
        })
    }

    @NonNull
    fun getUsersLiveData() : LiveData<Users> {
        return usersLiveData
    }

    @NonNull
    fun removeUsersLiveData() {
        USERS_REF.removeValue()
    }
}

为了在我的片段/活动中读取我的 Firebase 实时数据库,我执行以下操作:

val usersViewModel = ViewModelProvider(this).get(UsersViewModel::class.java)
val usersLiveData = usersViewModel.getUsersLiveData()
usersLiveData.observe(viewLifecycleOwner, object : Observer<Users> {
    override fun onChanged(users: Users?) {
        if (users != null) {
            firstName = users.firstName
            lastName = users.lastName
            today = users.today.toString()
            week = users.week.toString()
        }
    }
})

为了在我的片段/活动中写入我的 Firebase 实时数据库,我执行以下操作:

val updateUserChildValues = Firebase.database.getReference("users").child(auth.currentUser!!.uid)
updateUserChildValues.child("child-name").setValue(value)

现在的问题是当我更新数据库中的值时,有时侦听器不会立即获取更改。我要么必须去另一个破坏前一个活动的活动,回到旧活动,这样我才能看到新的变化,要么关闭应用程序并再次打开它。所以基本上应用程序需要刷新片段/活动来获得新的变化。

我应该怎么办?如何确保侦听器始终从我的数据库中获取新更改,以便立即更新 UI?或者我如何刷新我的片段/活动以确保用户总是立即看到新的变化?

标签: androidkotlinfirebase-realtime-databaseandroid-livedataandroid-viewmodel

解决方案


推荐阅读