观察evereverforever生命周期? [英] is observeForever lifecycle aware?

查看:98
本文介绍了观察evereverforever生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用MVVM,并且已经对其进行了不同的实现,但是仍然使我感到困惑的一件事是,如何在不将任何生命周期附加到ViewModel的情况下,从ViewModel的存储库(Firebase)中获取数据.

I'm working with MVVM, and I have made different implementations of it, but one thing that is still making me doubt is how do I get data from a Repository (Firebase) from my ViewModel without attaching any lifecycle to the ViewModel.

我已经从ViewModel实现了observeForever(),但是我认为这不是一个好主意,因为我认为我应该使用回调或Transformation从存储库向ViewModel进行通信.

I have implemented observeForever() from the ViewModel, but I don't think that is a good idea because I think I should communicate from my repository to my ViewModel either with a callback or a Transformation.

我在这里留下一个示例,其中我从Firebase获取设备并更新我的UI,如果可以在此处看到,我正在观察来自UI回购的数据,但是从ViewModel中,我也在观察数据在仓库中,我真的怀疑我是否使用了正确的方法,因为我不知道如果我的视图被破坏了,是否会在onCleared()上清除observeForever(),因此它不会保持如果视图消失,观察者还活着.

I leave here an example where I fetch a device from Firebase and update my UI, if we can see here, I'm observing the data coming from the repo from the UI, but from the ViewModel I'm also observing data from the repo, and here is where I really doubt if I'm using the right approach, since I don't know if observeForever() will be cleared on onCleared() if my view is destroyed, so it won't keep the observer alive if the view dies.

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button.setOnClickListener {
            val deviceId = editText.text.toString().trim()
            observeData(deviceId)
        }
    }

    fun observeData(deviceId:String){
        viewModel.fetchDeviceData(deviceId).observe(this, Observer {
            textView.text = "Tipo: ${it.devType}"
        })

ViewModel

class MainViewmodel: ViewModel() {

    private val repo = Repo()
    fun fetchDeviceData(deviceId:String):LiveData<Device>{
        val mutableData = MutableLiveData<Device>()
        repo.getDeviceData(deviceId).observeForever {
            mutableData.value = it
        }

        return mutableData
    }
}

存储库

class Repo {

    private val db = FirebaseDatabase.getInstance().reference
    fun getDeviceData(deviceId:String):LiveData<Device>{
        val mutableData = MutableLiveData<Device>()
        db.child(deviceId).child("config/device").addListenerForSingleValueEvent(object: ValueEventListener{

            override fun onDataChange(dataSnapshot: DataSnapshot) {
                    val device = dataSnapshot.getValue(Device::class.java)
                    mutableData.value = device
            }

            override fun onCancelled(dataError: DatabaseError) {
                Log.e("Error","handle error callback")
            }
        })

        return mutableData
    }
}

此示例仅显示了如何从Firebase提取设备,它可以工作,但是从我的ViewModel中,它使我一直认为observeForever()不是我想要的在存储库与ViewModel之间进行数据通信的对象.

This example just shows how to fetch the device from Firebase, it works, but from my ViewModel, it keeps making me think that observeForever() is not what I'm looking for to communicate data between the repository to the ViewModel.

我已经看过Transformations,但是在这种情况下,我只需要将整个Device对象交付给我的UI,因此不需要将要检索的对象转换为另一个Object

I have seen Transformations, but I, in this case, I just need to deliver the entire Device object to my UI, so I don't need to transform the Object I'm retrieving to another Object

在这里,正确地传达存储库和ViewModel的正确方法应该是什么?

What should be here the right approach to communicate the repository and the ViewModel properly?

推荐答案

observeForever生命周期知道吗?

is observeForever lifecycle aware?

不,这就是为什么它被称为observe Forever 的原因.

No, that's why it's called observeForever.

我已经从ViewModel中实现了observeForever(),但我认为这不是一个好主意

I have implemented observeForever() from the ViewModel, but I don't think that is a good idea

不,不是,您应该使用Transformations.switchMap {.

No, it's not, you should be using Transformations.switchMap {.

因为我不知道如果我的视图被破坏了,是否会在onCleared()上清除observeForever(),所以如果视图死了,它也不会使观察者存活.

since I don't know if observeForever() will be cleared on onCleared() if my view is destroyed, so it won't keep the observer alive if the view dies.

好吧,如果 您没有使用removeObserver(observer)onCleared()中清除它,则它不会清除自身,因为它会永远观察 .

Well if you're not clearing it in onCleared() using removeObserver(observer), then it won't clear itself, because it observes forever.

在这里,我真的怀疑我是否使用了正确的方法,

here is where I really doubt if I'm using the right approach,

不,采用反应性方法,您可以做得更好.

No, you can do much better than this following a reactive approach.

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

    button.setOnClickListener {
        val deviceId = editText.text.toString().trim()
        viewModel.onSelectedDeviceChanged(deviceId)
    }

    viewModel.selectedDevice.observe(this, Observer { device ->
        textView.text = "Tipo: ${device.devType}"
    })
}

还有

class MainViewModel: ViewModel() {
    private val repo = Repo() // TODO: move to Constructor Argument with ViewModelProvider.Factory

    private val selectedDeviceId = MutableLiveData<String>

    fun onSelectedDeviceChanged(deviceId: String) {
        selectedDeviceId.value = deviceId
    }

    val selectedDevice = Transformations.switchMap(selectedDeviceId) { deviceId ->
        repo.getDeviceData(deviceId)
    }
}

还有

class Repo {
    private val db = FirebaseDatabase.getInstance().reference // TODO: move to constructor arg? Probably

    fun getDeviceData(deviceId:String) : LiveData<Device> {
        return object: MutableLiveData<Device>() {
            private val mutableLiveData = this

            private var query: Query? = null
            private val listener: ValueEventListener = object: ValueEventListener {
                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    val device = dataSnapshot.getValue(Device::class.java)
                    mutableLiveData.value = device
                }

                override fun onCancelled(dataError: DatabaseError) {
                    Log.e("Error","handle error callback")
                }
            }

            override fun onActive() {
                query?.removeEventListener(listener)
                val query = db.child(deviceId).child("config/device")
                this.query = query
                query.addValueEventListener(listener)
            }

            override fun onInactive() {
                query?.removeEventListener(listener)
                query = null
            }
        }
    }
}

通过这种方式,您可以使用LiveData来观察Firebase中的更改(因此会通知您将来对值所做的更改),而不是仅执行一次提取操作,而无需知道在其他位置对同一数据所做的更改

This way, you can observe for changes made in Firebase (and therefore be notified of future changes made to your values) using LiveData, rather than only execute a single fetch and then not be aware of changes made elsewhere to the same data.

这篇关于观察evereverforever生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆