繁体   English   中英

将 Firebase 数据库 ChildEventListener 与 ViewModel 一起使用的正确方法是什么?

[英]What is the right way to use Firebase Database ChildEventListener with ViewModel?

在 Android OS 中,由于各种配置更改,例如方向更改,活动被销毁并重新创建。 但这也会导致更多的成本 - 例如重新获取数据以显示 UI。 因此,开发ViewModel是为了在活动真正被销毁之前保持数据存在 - 在配置更改期间保持安全。

我一直在我的应用程序中使用 Firebase 实时数据库,并且我对 Firebase SDK 中的ChildEventListener非常了解。 由于使用ViewModel有很多优点 - 我有兴趣在我的应用程序中使用它。 我已经阅读了有关ViewModel架构以及 Firebase 的各种资源、博客:但它们仅使用 ValueEvent 侦听器。 我在应用程序中显示RecyclerView ,而ChildEventListener是一个完美的候选者。

我想使用具有ViewModel架构的ChildEventListener维护一个列表。 我编写了代码来使用ViewModel主动获取数据。

class DataViewModel : ViewModel() {

    private var listenerRemovePending = false
    private val listener = MyChildEventListener()
    private val handler = Handler(Looper.getMainLooper())
    private lateinit var dataListRef: DatabaseReference

    var data: MutableLiveData<ArrayList<DataModel>> = MutableLiveData()
    val dataList: ArrayList<DataModel> = arrayListOf()

    fun getData(userId: String): LiveData<ArrayList<DataModel>> {
        dataListRef =
            FirebaseDatabase.getInstance().getReference("/data/$userId/data")
        dataListRef.addChildEventListener(object : ChildEventListener {
            override fun onCancelled(databaseError: DatabaseError) {
                Log.e(
                    LOG_TAG,
                    "Can't listen to query :dataListRef",
                    databaseError.toException()
                )
            }

            override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {
                TODO("Not yet implemented")
            }

            override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {
                TODO("Not yet implemented")
            }

            override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
                if (snapshot.exists()) {
                    val item: DataModel? =
                        snapshot.getValue(DataModel::class.java)
                    if (item != null) {
                        dataList.add(item)
                    }
                    data.value = dataList
                }
            }

            override fun onChildRemoved(snapshot: DataSnapshot) {
                TODO("Not yet implemented")
            }
        })
        return data
    }

    companion object {
        private const val LOG_TAG = "DataViewModel"
    }
}

我对它的结果很满意。 但这是一个主要问题 - 如果没有观察者(活动不活跃),我希望这个ChildEventListener被分离。 目前,此侦听器处于活动状态,直到活动结束 - 此ViewModel将保持其侦听器连接,直到调用 Activity 的onDestroy方法。

所以我的问题是如何从这里分离非活动 state 上的侦听器?

您应该在 ViewModel class 中覆盖 onCleared() function。 但是如果你想使用 MVVM 模式,你的网络请求应该在 SomRequestRemoteDataSource 中。

override fun onCleared() {
    super.onCleared()
    dataListRef.removeEventListener(yourChildListener)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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