繁体   English   中英

Android LiveData - 观察复杂/嵌套的对象

[英]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.

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