我有一个名为SharedViewModel的ViewModel:
public class SharedViewModel<T> extends ViewModel {
private final MutableLiveData<T> selected = new MutableLiveData<>();
public void select(T item) {
selected.setValue(item);
}
public LiveData<T> getSelected() {
return selected;
}
}
我是根据Google的Arch ViewModel参考页面上的SharedViewModel示例实现的:
活动中的两个或多个片段需要相互通信是很常见的。这两者都不是微不足道的 片段需要定义一些接口描述和所有者 活动必须将两者结合在一起。而且,两个片段都必须 处理尚未创建其他片段的情况 可见。
我有两个片段,分别叫ListFragment
和DetailFragment
。
到目前为止,我在被调用的MasterActivity
中使用了这两个片段。一切都运作良好。
我在ListFragment
中获得了ViewModel,选择了在DetailFragment
上使用它的值。
mStepSelectorViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
但是,现在我需要在某些情况下将ListFragment
(不同设备配置的布局)添加到名为DetailActivity
的其他活动中。有没有办法像上面的例子那样做?
答案 0 :(得分:10)
有点晚了,但你可以使用共享ViewModelStore
来完成此任务。片段和活动实现ViewModelStoreOwner
接口。在这些情况下,片段每个实例都有一个存储,活动将它保存在一个静态成员中(我想它可以在配置更改后继续存在)。
回到共享ViewModelStore
,例如,您希望它成为您的Application实例。您需要应用程序来实现ViewModelStoreOwner
。
class MyApp: Application(), ViewModelStoreOwner {
private val appViewModelStore: ViewModelStore by lazy {
ViewModelStore()
}
override fun getViewModelStore(): ViewModelStore {
return appViewModelStore
}
}
然后,如果您知道需要在活动边界之间共享ViewModel,则可以执行以下操作。
val viewModel = ViewModelProvider(myApp, viewModelFactory).get(CustomViewModel::class.java)
现在它将使用您应用中定义的商店。这样你就可以共享ViewModels。
非常重要。因为在此示例中ViewModels
存在于您的应用程序实例中,所以当使用它们的片段/活动被销毁时,它们不会被销毁。因此,您必须将它们链接到将使用它们的最后一个片段/活动的生命周期,或者手动销毁它们。
答案 1 :(得分:3)
好吧,我为此创建了一个名为Vita的库,您可以在活动之间共享ViewModel
,甚至可以在具有不同主机活动的片段之间共享:
val myViewModel = vita.with(VitaOwner.Multiple(this)).getViewModel<MyViewModel>()
以这种方式创建的ViewModel
一直存在,直到其最后一个LifeCycleOwner
被销毁为止。
您还可以创建ViewModel
并具有应用程序范围:
val myViewModel = vita.with(VitaOwner.None).getViewModel<MyViewModel>()
当用户关闭应用程序时,这种类型的ViewModel
将被清除
尝试一下,请告诉我您的反馈意见: https://github.com/FarshadTahmasbi/Vita
答案 2 :(得分:2)
你可以使用factory来制作viewmodel,这个因素将返回视图模型的单个对象。作为:
class ViewModelFactory() : ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
if (modelClass.isAssignableFrom(UserProfileViewModel::class.java)) {
val key = "UserProfileViewModel"
if(hashMapViewModel.containsKey(key)){
return getViewModel(key) as T
} else {
addViewModel(key, UserProfileViewModel())
return getViewModel(key) as T
}
}
throw IllegalArgumentException("Unknown ViewModel class")
}
companion object {
val hashMapViewModel = HashMap<String, ViewModel>()
fun addViewModel(key: String, viewModel: ViewModel){
hashMapViewModel.put(key, viewModel)
}
fun getViewModel(key: String): ViewModel? {
return hashMapViewModel[key]
}
}
}
活动:
viewModelFactory = Injection.provideViewModelFactory(this)
// Initialize Product View Model
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(
UserProfileViewModel::class.java)`
这将只提供UserProfileViewModel的单个对象,您可以在活动之间共享。
答案 3 :(得分:1)
我认为我们仍然对Android上的MVVM框架感到困惑。 对于另一项活动,请不要感到困惑,因为它必须相同,为什么?
如果它具有相同的逻辑(即使该逻辑在其他有用的类中仍然可以是抽象的),或者XML中的视图几乎相同,则这是有道理的。
让我们举个简单的例子:
我创建了一个名为vmA的ViewModel,并创建了一个名为A的活动,我需要用户的数据,我将在用户的vmA中插入存储库。
现在,我需要另一个活动,该活动需要读取用户数据, 我创建另一个名为vmB的ViewModel,并在其中调用用户存储库。 如上所述,存储库始终相同。
已经建议的另一种方法是使用Factory的实现创建同一ViewModel的N个实例。
答案 4 :(得分:1)
如果您希望所有活动(而不是某些活动)共享一个ViewModel, 那为什么不存储要在该ViewModel中存储的内容 在您的Application类中?
上一届Google I / O大会上提出的趋势似乎是放弃“活动”的概念,而转而使用具有很多“片段”的单活动应用程序。 ViewModels是删除接口以前必须实现的接口的大量方法。 因此,这种方式不再导致巨大且不可维持的活动。
答案 5 :(得分:-2)