我实现了一个最初实现android.arch.lifecycle.Observer的片段,我想开始观察其他一些实时数据,但不能。我从这个开始:
class MyFragment : BaseFragment(), Observer<FragmentData> {
lateinit var viewModel: MyViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.fragmentData.observe(this, this)
}
override fun onChanged(data: FragmentData?) {
activity?.title = getTitleFromData(data)
}
}
如果我更新类以包含其他可观察的数据,如下所示:
class MyFragment : BaseFragment(), Observer<FragmentData>, Observer<OtherData> {
lateinit var viewModel: MyViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
viewModel.fragmentData.observe(this, this)
}
override fun onChanged(otherData: OtherData) {
// update UI from otherData
}
override fun onChanged(data: FragmentData?) {
activity?.title = getTitleFromData(data)
}
}
我收到一个错误:
"观察器"的类型参数 T 的值不一致: 碎片数据,其他数据 超类型出现两次
我希望得到一些帮助,以了解为什么编译器无法辨别类型之间的差异并想知道最佳替代模式。
像这样的东西?
viewModel.fragmentData.observe(this, fragmentDataObserver)
private val fragmentDataObserver = Observer<Fragmentdata> {
activity?.title = getTitleFromData(it)
}
你可以尝试实现一个通用的观察器接口,如下所示:
class MyFragment : BaseFragment(), Observer<Any> {...}
然后在 onChanged 方法使用
override fun onChanged(any: Any?) {
when:
any is isOtherData -> Do OtherData things
any is FragmentData -> Do FragmentData things
}
第二种解决方法是创建 OtherData 和 FragmentData 的父类,FatherInterface 只是一个接口,主体中没有任何内容:
interface OtherData: FatherInterface{}...
interface FragmentData : FatherInterface{}...
然后你可以做
class MyFragment : BaseFragment(), Observer<FatherInterface>{}...
override fun onChanged(fatherInterface: FatherInterface?) {
when{
fatherInterface is OtherData -> ...
fatherInterface is FragmentData -> ...
}
// update UI from otherData
}
由于类型擦除,编译器无法识别类型之间的差异。当程序编译时,几乎所有泛型信息都会从类中剥离。不再有Observer<FragmentData>
和Observer<OtherData>
,只有一个Observer
类。现在,如果没有类型擦除,这样的事情是有意义的
class MyFragment : BaseFragment(), Observer<FragmentData>, Observer<OtherData> {
override fun onChanged(otherData: OtherData) {
// update UI from otherData
}
override fun onChanged(data: FragmentData?) {
activity?.title = getTitleFromData(data)
}
}
但是一旦你应用了类型擦除,那么你基本上就是在尝试两次扩展同一个类,并为同一个基本方法提供两种不同的覆盖方法,这是不允许的。所以这就是为什么编译器不让你这样做的原因。这是我以有限的知识所能给出的准确描述。
至于另一种选择,就像评论建议的那样,尝试使用 lambda 而不是尝试使片段本身成为双重观察者。
class MyFragment : BaseFragment(), Observer<OtherData> {
lateinit var viewModel: MyViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel.fragmentData.observe(this, Observer { onChanged(it) })
}
override fun onChanged(otherData: OtherData?) {
// update UI from otherData
}
private fun onChanged(data: FragmentData?) {
activity?.title = getTitleFromData(data)
}
}