在不同Activity中的片段之间共享ViewModel

ale*_*pfx 22 android viewmodel android-fragments android-activity android-architecture-lifecycle

我有一个名为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在Google的Arch ViewModel参考页面上基于SharedViewModel示例实现它:

https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing_data_between_fragments

活动中的两个或更多个片段需要彼此通信是很常见的.这绝不是微不足道的,因为两个片段都需要定义一些接口描述,并且所有者活动必须将两者绑定在一起.而且,两个片段必须处理尚未创建或不可见的其他片段的情况.

我有两个片段,叫做ListFragmentDetailFragment.

到现在为止我用里面称这两个片段MasterActivity.一切都运作良好.

我得到了ViewModel ListFragment,选择了要使用它的值DetailFragment.

mStepSelectorViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
Run Code Online (Sandbox Code Playgroud)

但是,现在我需要在某些情况下ListFragment(将不同设备配置的布局)添加到另一个名为的活动中DetailActivity.有没有办法像上面的例子那样做?

mik*_*ehc 14

有点晚了但你可以用共享来完成这个ViewModelStore.片段和活动实现了ViewModelStoreOwner接口.在这些情况下,片段每个实例都有一个存储,并且活动将它保存在静态成员中(我猜它可以在配置更改中存活).

回到共享ViewModelStore,比如说你希望它成为你的Application实例.您需要应用程序来实现ViewModelStoreOwner.

class MyApp: Application(), ViewModelStoreOwner {
    private val appViewModelStore: ViewModelStore by lazy {
        ViewModelStore()
    }

    override fun getViewModelStore(): ViewModelStore {
        return appViewModelStore
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,如果您知道需要在活动边界之间共享ViewModel,则可以执行此类操作.

val viewModel = ViewModelProvider(myApp, viewModelFactory).get(CustomViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)

所以现在它将使用您的应用中定义的商店.这样你就可以共享ViewModels.

很重要.因为在此示例中ViewModels,当您使用它们的片段/活动被销毁时,它们不会被销毁.因此,您必须将它们链接到将使用它们的最后一个片段/活动的生命周期,或者手动销毁它们.


Far*_*sbi 5

好吧,我为此创建了一个名为Vita的库,您可以ViewModel在不同宿主活动的活动甚至片段之间共享s:

val myViewModel = vita.with(VitaOwner.Multiple(this)).getViewModel<MyViewModel>()
Run Code Online (Sandbox Code Playgroud)

ViewModel以这种方式创造的东西会一直活着,直到它的最后一个LifeCycleOwner被摧毁。

您也可以创建ViewModel具有应用程序范围的 s:

val myViewModel = vita.with(VitaOwner.None).getViewModel<MyViewModel>()
Run Code Online (Sandbox Code Playgroud)

ViewModel当用户关闭应用程序时,这种类型将被清除

试一试,请让我知道您的反馈:https : //github.com/FarshadTahmasbi/Vita


Mun*_*kur 4

你可以使用工厂来制作视图模型,这个因素将返回视图模型的单个对象。如下所示:

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]
    }
}
}
Run Code Online (Sandbox Code Playgroud)

活动中:

viewModelFactory = Injection.provideViewModelFactory(this)

// Initialize Product View Model
userViewModel = ViewModelProviders.of(this, viewModelFactory).get(
UserProfileViewModel::class.java)`
Run Code Online (Sandbox Code Playgroud)

这将仅提供您可以在活动之间共享的 UserProfileViewModel 的单个对象。