android 在ViewModel之间共享数据

i7uq4tfw  于 11个月前  发布在  Android
关注(0)|答案(4)|浏览(116)

我的项目中有一个复杂的屏幕,我将其分解为多个片段。我尝试遵循MVVM架构来创建这些类,因此哪个片段有自己的ViewModel和Contract类。
问题是,所有ViewModel都需要相同的对象示例(我们称之为Book)来执行Room事务。
它是否有一个正确的方法来在ViewModel之间共享数据(或LiveData)?我知道共享ViewModel的概念,但我不知道我是否可以将其应用到这个案例中。我也想过使用MediatorLiveData,但没有得到一个很好的方法。
我正在考虑创建一个带有LiveData<Book>(或Rx Subject<Book>)的类(我们称之为BookObservableProvider),其中每个ViewModel注入相同的示例,并始终加载/更新相同的值。
这是个好方法吗?

p8h8hvxi

p8h8hvxi1#

您应该在片段/活动之间共享这些数据(可能对活动使用Intent),然后由其他ViewModel处理这些数据

kpbwa7wx

kpbwa7wx2#

如果你的问题背后的原因是房间访问,那么建议有一个DataRepository类来处理所有的数据库访问,你只需要把这个仓库单例传递给每个AndroidViewModel

mRepository = ((MainApp) application).getRepository();

字符串
在MainApp中:

public DataRepository getRepository() {
    return DataRepository.getInstance(getDatabase(), mAppExecutors);
}


关于Repository:

public class DataRepository {

    private static DataRepository sInstance;
    private MediatorLiveData<String> mObservableString;

    private DataRepository(final AppDatabase database, final AppExecutors executors) {
        mObservableString.addSource(database.myDao().loadString(),
            mString -> {
                if (database.getDatabaseCreated().getValue() != null) {
                    mObservableString.postValue(mString);
                }
            });
    }

    public static DataRepository getInstance(final AppDatabase database, final AppExecutors executors) {
        if (sInstance == null) {
            synchronized (DataRepository.class) {
                if (sInstance == null) {
                    sInstance = new DataRepository(database, executors);
                }
            }
        }
        return sInstance;
    }
    
    // and then your access methods
    
    public LiveData<String> getString() {
        return mObservableString;
    }


在仓库中,如果你想改变引用(源),建议使用MediatorLiveData。否则,普通LiveData会完成这项工作。

关于ViewModels:

理论上,每个片段都有自己的ViewModel。如果你使用requireActivity()作为引用来获取它,你就可以在任何地方获取每个ViewModel,并因此共享它。
例如:

viewModelA = new ViewModelProvider(requireActivity()).get(ViewModelA.class);
    viewModelB = new ViewModelProvider(requireActivity()).get(ViewModelB.class);


如果DataRepository的设置对你来说有点过分的话,你可以创建一个具有Room访问权限的ViewModel,然后从每个Fragment中加载它。

a64a0gku

a64a0gku3#

我也面临着同样的问题,但是如果你没有为不同的片段使用不同的视图模型,或者设计不需要为不同的片段使用不同的视图模型,你可以在整个Activity之间共享一个片段(所有其他片段),它们将共享相同的数据示例。
点击此链接获取更多https://developer.android.com/guide/fragments/communicate
您需要做的是确保所有片段都使用相同的上下文启动视图模型(主视图模型)。

public class FilterFragment extends Fragment {
    private ListViewModel viewModel;

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        viewModel = new ViewModelProvider(requireActivity()).get(ListViewModel.class);
        viewModel.getFilters().observe(getViewLifecycleOwner(), set -> {
            // Update the selected filters UI
        });
    }
}

字符串
注意到本

viewModel = new ViewModelProvider(requireActivity()).get(ListViewModel.class);


requireActivity()确保所有片段都调用宿主Activity的上下文。
但是,您不能以这种方式与Activity共享数据,因为视图模型示例在Activity被销毁时也被销毁

2skhul33

2skhul334#

在我个人看来,你的方法对于这种情况来说并不坏,但是如果想尝试其他方法,我可以建议你使用RxBus方法。这里有一个很棒的article。使用这种方法,你可以简单地在Activity中发布数据,其中包含片段,然后在所有片段中监听这个特定的事件。
类似于:

//Activity
RxBus.publish(RxEvent.EventOnBookProvide(bookObject)

字符串

//Fragment
RxBus.listen(RxEvent.EventOnBookProvide::class.java).subscribe {
        useObject(it)
    }


如果使用Activity,不要忘记在onDestroy()中使用Disposable和.dispose();如果使用fragment,请在onDestroyView()中使用Disposable和. dispose()。

相关问题