示例ViewModel:
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<>();
}
return mCurrentName;
}
}
主要活动:
mModel = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = textView::setText;
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
我想在第二个活动中调用mModel.getCurrentName().setValue(anotherName);
并让MainActivity接收更改。这可能吗?
答案 0 :(得分:24)
当您致电ViewModelProviders.of(this)
时,实际上您创建/保留了绑定到ViewModelStore
的{{1}},因此不同的活动有不同的this
和每个ViewModelStore
使用给定工厂创建ViewModelStore
的不同实例,因此您不能在不同的ViewModel
s中拥有ViewModel
的相同实例。
但是您可以通过传递充当单件工厂的自定义ViewModel工厂的单个实例来实现此目的,因此它将始终在不同活动中传递ViewModelStore
的同一实例。
例如:
ViewModel
所以你需要的是使public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {
NameViewModel t;
public SingletonNameViewModelFactory() {
// t = provideNameViewModelSomeHowUsingDependencyInjection
}
@Override
public NameViewModel create(Class<NameViewModel> modelClass) {
return t;
}
}
单身(例如使用Dagger)并像这样使用它:
SingletonNameViewModelFactory
注意:强>
在不同的范围内保留mModel = ViewModelProviders.of(this,myFactory).get(NameViewModel.class);
是一种反模式。强烈建议您保留数据层对象(例如,制作数据源或存储库单例)并在不同范围(活动)之间保留数据。
阅读this文章了解详情。
答案 1 :(得分:9)
使用ViewModelProviders获取视图模型时,您将作为生命周期所有者传递MainActivity,这将为该活动提供视图模型。在第二个活动中,您将获得该ViewModel的不同实例,这次是您的第二个活动。第二个模型将有第二个实时数据。
您可以做的是将数据保存在不同的层中,例如存储库,它可以是单例,也可以使用相同的视图模型。
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = DataRepository.getInstance().getCurrentName();
}
return mCurrentName;
}
}
//SingleTon
public class DataRepository
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<>();
}
return mCurrentName;
}
//Singleton code
...
}
答案 2 :(得分:0)
只需创建您的 ViewModel 的实例,在本例中为 NameViewModel
您的ViewModel Factory就像
class ViewModelFactory : ViewModelProvider.NewInstanceFactory() {
override fun <T : ViewModel?> create(modelClass: Class<T>) =
with(modelClass){
when {
isAssignableFrom(NameViewModel::class.java) -> NameViewModel.getInstance()
else -> throw IllegalArgumentException("Unknown viewModel class $modelClass")
}
} as T
companion object {
private var instance : ViewModelFactory? = null
fun getInstance() =
instance ?: synchronized(ViewModelFactory::class.java){
instance ?: ViewModelFactory().also { instance = it }
}
}
}
还有您的ViewModel
class NameViewModel : ViewModel() {
//your liveData objects and many more...
companion object {
private var instance : NameViewModel? = null
fun getInstance() =
instance ?: synchronized(NameViewModel::class.java){
instance ?: NameViewModel().also { instance = it }
}
}
}
现在,您可以使用ViewModelProviders
来获取同一ViewModel实例,以在任何活动中使用
ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(NameViewModel::class.java)
OR
创建扩展功能以方便访问
fun <T : ViewModel> AppCompatActivity.getViewModel(viewModelClass: Class<T>) =
ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(viewModelClass)