我正在尝试使用泛型来实现viewmodel观察器,这样做是因为我要从7个不同的Fragments中收集数据,所以我不需要7个观察器。
由于这7个片段将数据存储在不同的ArrayLists类型中,所以我制作了一个通用的ViewModel类,以将该数据传递给我的主Activity(片段持有者)
class SharedViewModel<T>: ViewModel() {
var data:MutableLiveData<ArrayList<T>> = MutableLiveData()
fun setData(anyData:ArrayList<T>){
data.value = anyData
}
val getAnyData:LiveData<ArrayList<T>>
get() = data
}
这样做,我只需在每个片段内设置任何数组数据类型
(activity as MainActivity).getViewModelInstance().setData(xArray)
在我的MainActivity中,我想检查xArray数据类型是否与MainActivity全局声明的类型相同,如果它们相等,则应将当前数组数据值赋给新的空数组
private var xArray = arrayListOf<Xclass>()
onCreate()
...
viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
viewModel.getAnyData.observe(this, Observer { it:ArrayList<out Any?>
if(it == xArray){
xArray.addAll(it)
}
})
如果这样做,我将避免在MainActivity中为每个片段做7个观察者,而只用一个不同的数组类型更新一个观察者,对它们进行比较并重新分配它们将减少代码量,并且对我来说更容易实现体系结构。
有两个问题
ArrayLists
第二个错误是这个
(活动为MainActivity).getViewModelInstance()。setData(xArray)
在.setData(xArray)
的红色突出显示为Required: Nothing, Found:ArrayList<Xclass>
。太奇怪了,因为SharedViewModel的setData需要传递任何ArrayList。
谢谢
答案 0 :(得分:1)
经过深思熟虑,我提出了一种简单但并非失败的方法,即通过将类类型与泛型结合使用以实现全部功能。我相信这将解决您的可重用性问题,并以您希望的方式删除多余的侦听器。
class SharedViewModel <T> (val listType: Class<T>) : ViewModel() {
var data: MutableLiveData<ArrayList<T>> = MutableLiveData()
fun setData(anyData: ArrayList<T>) {
data.value = anyData
}
inline fun <reified K> isOfInternalType(checkType: Class<K>): Boolean = checkType.typeName == listType.typeName
}
class Xclass
var xArray = arrayListOf<Xclass>()
val viewModel = (activity as MainActivity).getViewModelInstance()
if (viewModel.isOfInternalType(Xclass::class.java) {
viewModel.setData(Xclass)
}
class Xclass
private var xArray = arrayListOf<Xclass>()
onCreate()
...
viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
viewModel.getAnyData.observe(this, Observer { data: ArrayList<out Any?> ->
if (viewModel.isOfInternalType(Xclass::class.java) {
xArray.addAll(it)
}
})
// Examples of use cases outside of initial question
class ViewOne: SharedView<ClassOne>(ClassOne::class.java)
val testClass = ViewOne()
ViewOne().isOfInternalType(ClassTwo::class.java) // returns false
ViewOne().isOfInternalType(testClass::class.java) // Error: Cannot use captured type as reified parameter
ViewOne().isOfInternalType(ClassOne::class.java) // returns true
ViewOne().isOfInternalType(ClassOne().javaClass) // returns true
testClass.isOfInternalType(ClassOne::class.java) // returns true
我所做的是创建一个实例化时所需的View的listType实例。之所以需要这样做,是因为类不像内联函数那样支持类型化。 此实现假定每个View都有一个静态listType ...可以将其修改为类似于以下内容:
class SharedViewModel(listType: Class<*>) : ViewModel() {
var listType: Class<*> = listType
private set(value) {
field = value
}
fun setData(anyData: ArrayList<*>) {
data.value = anyData
}
fun updateListType(newType: Class<*>) {
listType = newType
}
inline fun <reified K> isOfInternalType(checkType: Class<K>): Boolean =
checkType.typeName == listType.typeName
}
class ViewOne: SharedView(ClassOne::class.java)
val testClass = ViewOne()
testClass.isOfInternalType(ClassOne::class.java) // returns true
testClass.updateListType(ClassTwo::class.java)
testClass.isOfInternalType(ClassOne::class.java) // returns false now
testClass.isOfInternalType(ClassTwo::class.java) // returns true now
使用变量键入的这种实现,您希望将isOfInternalType
与setData
链接起来,以确保类型安全
它应该具有足够的功能来实现该项目的体系结构目标,如果我误解了任何内容并可以提供进一步的帮助,请告诉我。