[英]Android LiveData - observe complex/nested objects
我正在使用 MVVM 结构开发一个 android 项目。 我想按照推荐使用 LiveData。 在示例中,总是只有简单的对象类型,例如字符串。 但我想将更复杂/嵌套的对象类型放入 LiveData。
例如像这样的对象结构:
class ClassA {
private var testVarB = ClassB()
fun getTestVarB(): ClassB {
return this.testVarB
}
fun setTestVarB(classB: ClassB) {
this.testVarB = classB
}
fun setTxt(str: String) {
this.testVarB.getTestVarC().setStr(str)
}
}
class ClassB {
private var testVarC = ClassC()
fun getTestVarC(): ClassC {
return this.testVarC
}
fun setTestVarB(classC: ClassC) {
this.testVarC = classC
}
}
class ClassC {
private var str: String = "class C"
fun getStr(): String {
return this.str
}
fun setStr(str: String) {
if (str != this.str) {
this.str = str
}
}
}
我的 ViewModel 看起来像这样:
class MyViewModel : ViewModel() {
var classAObj= ClassA()
private var _obj: MutableLiveData<ClassA> = MutableLiveData()
val myLiveData: LiveData<ClassA> = _obj
init {
_obj.value = classAObj
}
}
在片段中观察到 LiveDataObject:
class FirstFragment : Fragment() {
private var viewModel = MyViewModel()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
...
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.myLiveData.observe(
requireActivity(),
Observer<ClassA>() {
// should get fired!
Log.d("TAG", "update view")
})
}
}
因此,如果ClassC
的变量str
更改,则应执行回调。 我正在寻找一个聪明而简单的解决方案。
我刚刚发现了这个类似的帖子: LiveData update on object field change
此示例的深度为 1。但我正在寻找具有任意深度的解决方案。
我无法为我的问题找到解决方案的样本这一事实让我感到怀疑。 所以我想我的方法无论如何都是错误或不好的做法。 也许我应该寻找一种方法来分解事物并仅观察简单的对象。
有没有人对此有解决方案或意见?
谢谢你的帮助!
这是我制定的解决方案:
我从这里使用 PropertyAwareMutableLiveData 类: LiveData update on object field change
class PropertyAwareMutableLiveData<T : BaseObservable> : MutableLiveData<T>() {
private val callback = object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
value = value
}
}
override fun setValue(value: T?) {
super.setValue(value)
value?.addOnPropertyChangedCallback(callback)
}
}
基于此,我使用 iterface/abstract 类扩展了模型。
abstract class InterfaceObservable : BaseObservable() {
open fun setNewString(s: String) {
notifyPropertyChanged(BR.str)
}
}
class ClassA : InterfaceObservable() {
private var testVarB = ClassB()
fun getTestVarB(): ClassB {
return this.testVarB
}
fun setTestVarB(classB: ClassB) {
this.testVarB = classB
}
override fun setNewString(s: String) {
super.setNewString(s)
this.testVarB.setNewString(s)
}
}
class ClassB {
private var testVarC = ClassC()
fun getTestVarC(): ClassC {
return this.testVarC
}
fun setTestVarB(classC: ClassC) {
this.testVarC = classC
}
fun setNewString(s: String) {
this.testVarC.setStr(s)
}
}
class ClassC : BaseObservable() {
@Bindable
private var str: String = "class C"
fun getStr(): String {
return this.str
}
fun setStr(str: String) {
if (str != this.str) {
this.str = str
}
}
}
在我的 ViewModel 中,我使用了 PropertyAwareMutableLiveData 类。
class MyViewModel() : ViewModel() {
var classAObj: ClassA = ClassA()
val myLiveData = PropertyAwareMutableLiveData<ClassA>()
init {
myLiveData.value = classAObj
}
}
在 Fragment 中,我可以观察到 LiveData 对象。 如果 ClassC.str 更改,观察者将收到通知并可以更改 UI。
class MyFragment : Fragment() {
private lateinit var viewModel: MyViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.myLiveData.observe(
viewLifecycleOwner,
Observer<ClassA> {
Log.d("TAG", "change your UI here")
})
}
}
与您的 UI 相关的每个属性都应该只能在InterfaceObservable
类给出的接口上更改。 这就是为什么这不是一个完美的解决方案的原因。 但也许在你的情况下这是合理的。
问题出在您创建 ViewModel 的方式上。 你不能直接实例化它。 如果您使用 fragment-ktx 工件,您可以这样做:
private val model: SharedViewModel by activityViewModels()
片段有自己的生命周期。 所以你应该用 viewLifeCycleOwner 替换 requireActivity()
viewModel.myLiveData.observe(
viewLifeCycleOwner,
Observer<ClassA>() {
// should get fired!
Log.d("TAG", "update view")
})
更多信息: https : //developer.android.com/topic/libraries/architecture/viewmodel#sharing
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.