observeForever 生命周期感知吗?
is observeForever lifecycle aware?
我正在使用 MVVM,我已经对它进行了不同的实现,但仍然让我怀疑的一件事是如何从我的 ViewModel 的存储库 (Firebase) 获取数据而不附加任何生命周期视图模型。
我已经从 ViewModel 实现了 observeForever()
,但我认为这不是一个好主意,因为我认为我应该使用回调或转换从我的存储库到我的 ViewModel 进行通信。
我在这里留下一个例子,我从 Firebase 获取设备并更新我的 UI,如果我们能看到这里,我正在观察来自 UI 的 repo 的数据,但是从 ViewModel 我也在观察来自 repo 的数据,在这里我真的怀疑我是否使用了正确的方法,因为我不知道 observeForever()
是否会在 onCleared()
如果我的视图被销毁,那么如果视图死了,它不会让观察者活着。
UI
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}"
})
视图模型
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。
我看到了Transformations
,但是我,在这种情况下,我只需要将整个Device对象传递给我的UI,所以我不需要转换我的对象' m 检索到另一个对象
正确传达存储库和 ViewModel 的正确方法应该是什么?
要使用ObserveForever,需要移除ViewModel中onClear里面的observer。
在这种情况下,我建议使用转换,即使您只需要直接映射而不对数据进行任何处理,这实际上与您对 observerForever 的观察者所做的相同。
observeForever()
不了解生命周期,将继续 运行 直到 removeObserver()
被调用。
在您的 ViewModel 中执行此操作,
class MainViewmodel: ViewModel() {
private val repo = Repo()
private var deviceData : LiveData<Device>? = null
fun fetchDeviceData(deviceId:String):LiveData<Device>{
deviceData = repo.getDeviceData(deviceId)
return deviceData!!
}
}
is observeForever lifecycle aware?
不,这就是为什么它被称为observe
Forever.
I have implemented observeForever() from the ViewModel, but I don't think that is a good idea
不,不是,你应该使用 Transformations.switchMap {
。
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.
好吧,如果 你 没有在 onCleared()
中使用 removeObserver(observer)
清除它,那么它就不会' t 清除自身,因为它观察到 forever.
here is where I really doubt if I'm using the right 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(
private val savedStateHandle: SavedStateHandle,
): ViewModel() {
private val repo = Repo() // TODO: move to Constructor Argument with ViewModelProvider.Factory
private val selectedDeviceId: MutableLiveData<String> = savedStateHandle.getLiveData<String>("selectedDeviceId")
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 中所做的更改(因此会收到有关您值的未来更改的通知),而不是只执行一次提取,然后不知道其他地方所做的更改相同的数据。
我正在使用 MVVM,我已经对它进行了不同的实现,但仍然让我怀疑的一件事是如何从我的 ViewModel 的存储库 (Firebase) 获取数据而不附加任何生命周期视图模型。
我已经从 ViewModel 实现了 observeForever()
,但我认为这不是一个好主意,因为我认为我应该使用回调或转换从我的存储库到我的 ViewModel 进行通信。
我在这里留下一个例子,我从 Firebase 获取设备并更新我的 UI,如果我们能看到这里,我正在观察来自 UI 的 repo 的数据,但是从 ViewModel 我也在观察来自 repo 的数据,在这里我真的怀疑我是否使用了正确的方法,因为我不知道 observeForever()
是否会在 onCleared()
如果我的视图被销毁,那么如果视图死了,它不会让观察者活着。
UI
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}"
})
视图模型
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。
我看到了Transformations
,但是我,在这种情况下,我只需要将整个Device对象传递给我的UI,所以我不需要转换我的对象' m 检索到另一个对象
正确传达存储库和 ViewModel 的正确方法应该是什么?
要使用ObserveForever,需要移除ViewModel中onClear里面的observer。
在这种情况下,我建议使用转换,即使您只需要直接映射而不对数据进行任何处理,这实际上与您对 observerForever 的观察者所做的相同。
observeForever()
不了解生命周期,将继续 运行 直到 removeObserver()
被调用。
在您的 ViewModel 中执行此操作,
class MainViewmodel: ViewModel() {
private val repo = Repo()
private var deviceData : LiveData<Device>? = null
fun fetchDeviceData(deviceId:String):LiveData<Device>{
deviceData = repo.getDeviceData(deviceId)
return deviceData!!
}
}
is observeForever lifecycle aware?
不,这就是为什么它被称为observe
Forever.
I have implemented observeForever() from the ViewModel, but I don't think that is a good idea
不,不是,你应该使用 Transformations.switchMap {
。
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.
好吧,如果 你 没有在 onCleared()
中使用 removeObserver(observer)
清除它,那么它就不会' t 清除自身,因为它观察到 forever.
here is where I really doubt if I'm using the right 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(
private val savedStateHandle: SavedStateHandle,
): ViewModel() {
private val repo = Repo() // TODO: move to Constructor Argument with ViewModelProvider.Factory
private val selectedDeviceId: MutableLiveData<String> = savedStateHandle.getLiveData<String>("selectedDeviceId")
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 中所做的更改(因此会收到有关您值的未来更改的通知),而不是只执行一次提取,然后不知道其他地方所做的更改相同的数据。