android 在ViewModel之间共享数据

i7uq4tfw  于 2024-01-04  发布在  Android
关注(0)|答案(4)|浏览(137)

我的项目中有一个复杂的屏幕,我将其分解为多个片段。我尝试遵循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

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

字符串
在MainApp中:

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


关于Repository:

  1. public class DataRepository {
  2. private static DataRepository sInstance;
  3. private MediatorLiveData<String> mObservableString;
  4. private DataRepository(final AppDatabase database, final AppExecutors executors) {
  5. mObservableString.addSource(database.myDao().loadString(),
  6. mString -> {
  7. if (database.getDatabaseCreated().getValue() != null) {
  8. mObservableString.postValue(mString);
  9. }
  10. });
  11. }
  12. public static DataRepository getInstance(final AppDatabase database, final AppExecutors executors) {
  13. if (sInstance == null) {
  14. synchronized (DataRepository.class) {
  15. if (sInstance == null) {
  16. sInstance = new DataRepository(database, executors);
  17. }
  18. }
  19. }
  20. return sInstance;
  21. }
  22. // and then your access methods
  23. public LiveData<String> getString() {
  24. return mObservableString;
  25. }


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

关于ViewModels:

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

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


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

展开查看全部
a64a0gku

a64a0gku3#

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

  1. public class FilterFragment extends Fragment {
  2. private ListViewModel viewModel;
  3. @Override
  4. public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
  5. viewModel = new ViewModelProvider(requireActivity()).get(ListViewModel.class);
  6. viewModel.getFilters().observe(getViewLifecycleOwner(), set -> {
  7. // Update the selected filters UI
  8. });
  9. }
  10. }

字符串
注意到本

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


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

展开查看全部
2skhul33

2skhul334#

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

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

字符串

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


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

展开查看全部

相关问题