繁体   English   中英

Android LiveData-如何在不同活动中重用相同的ViewModel?

[英]Android LiveData - how to reuse the same ViewModel on different activities?

示例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接收更改。 那可能吗?

当你调用ViewModelProviders.of(this) ,实际上创建/保留ViewModelStore这势必会this ,所以不同的活动有不同的ViewModelStore每个ViewModelStore创建的不同实例ViewModel使用给定的工厂,所以你不能有不同ViewModelStore中的ViewModel相同实例。

但是,您可以通过传递充当单例工厂的自定义ViewModel工厂的单个实例来实现此目的,因此它将始终在不同的活动之间传递相同的ViewModel实例。

例如:

public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {


    NameViewModel t;

    public SingletonNameViewModelFactory() {
      //  t = provideNameViewModelSomeHowUsingDependencyInjection
    }

    @Override
    public NameViewModel create(Class<NameViewModel> modelClass) {
        return t;
    }
}

因此,您需要使SingletonNameViewModelFactory单身(例如,使用Dagger)并像这样使用它:

mModel = ViewModelProviders.of(this,myFactory).get(NameViewModel.class);

注意:

在不同范围之间保留ViewModel是一种反模式。 强烈建议保留您的数据层对象(例如,使您的DataSource或Repository单例),并在不同范围(活动)之间保留数据。

阅读文章的详细信息。

当使用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
...
}

只需创建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)

要么

创建扩展功能以便于访问

fun <T : ViewModel> AppCompatActivity.getViewModel(viewModelClass: Class<T>) =
    ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(viewModelClass)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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