[单个ViewModel中的多个LiveData对象

问题描述 投票:2回答:1

我的应用程序的结构如下:

  • MainActivity(Activity) containing Bottom Navigation View with three fragments nested below
    • HomeFragment(Fragment) containing TabLayout with ViewPager with following two tabs
      • Journal (Fragment)
      • 书签(Fragment)
    • 片段B (Fragment)
    • 片段C (Fragment)

我正在使用Room维护所有日记记录。我在Journal and Bookmarks片段中每个观察一个LiveData对象。这些LiveData对象由我的JournalViewModel类返回。

JournalDatabase.java

public abstract class JournalDatabase extends RoomDatabase {

    private static final int NUMBER_OF_THREADS = 4;
    static final ExecutorService dbWriteExecutor = Executors.newFixedThreadPool(NUMBER_OF_THREADS);

    private static JournalDatabase INSTANCE;

    static synchronized JournalDatabase getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(), JournalDatabase.class, "main_database")
                    .fallbackToDestructiveMigration()
                    .build();
        }
        return INSTANCE;
    }

    public abstract JournalDao journalDao();
}

JournalRepository.java

public class JournalRepository {
    private JournalDao journalDao;
    private LiveData<List<Journal>> allJournals;
    private LiveData<List<Journal>> bookmarkedJournals;

    public JournalRepository(Application application) {
        JournalDatabase journalDatabase = JournalDatabase.getInstance(application);
        journalDao = journalDatabase.journalDao();
        allJournals = journalDao.getJournalsByDate();
        bookmarkedJournals = journalDao.getBookmarkedJournals();
    }

    public void insert(Journal journal) {
        JournalDatabase.dbWriteExecutor.execute(() -> {
            journalDao.insert(journal);
        });
    }

    public void update(Journal journal) {
        JournalDatabase.dbWriteExecutor.execute(() -> {
            journalDao.update(journal);
        });
    }

    public void delete(Journal journal) {
        JournalDatabase.dbWriteExecutor.execute(() -> {
            journalDao.delete(journal);
        });
    }

    public void deleteAll() {
        JournalDatabase.dbWriteExecutor.execute(() -> {
            journalDao.deleteAll();
        });
    }

    public LiveData<List<Journal>> getAllJournals() {
        return allJournals;
    }

    public LiveData<List<Journal>> getBookmarkedJournals() {
        return bookmarkedJournals;
    }
}

JournalViewModel.java

public class JournalViewModel extends AndroidViewModel {
    private JournalRepository repository;
    private LiveData<List<Journal>> journals;
    private LiveData<List<Journal>> bookmarkedJournals;

    public JournalViewModel(@NonNull Application application) {
        super(application);
        repository = new JournalRepository(application);
        journals = repository.getAllJournals();
        bookmarkedJournals = repository.getBookmarkedJournals();
    }

    public void insert(Journal journal) {
        repository.insert(journal);
    }

    public void update(Journal journal) {
        repository.update(journal);
    }

    public void delete(Journal journal) {
        repository.delete(journal);
    }

    public void deleteAll() {
        repository.deleteAll();
    }

    public LiveData<List<Journal>> getAllJournals() {
        return journals;
    }

    public LiveData<List<Journal>> getBookmarkedJournals() {
        return bookmarkedJournals;
    }
}

我正在两个片段的onActivityCreated()方法内部实例化此ViewModel。

JournalFragment.java

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    JournalFactory factory = new JournalFactory(requireActivity().getApplication());
    journalViewModel = new ViewModelProvider(requireActivity(), factory).get(JournalViewModel.class);
    journalViewModel.getAllJournals().observe(getViewLifecycleOwner(), new Observer<List<Journal>>() {
        @Override
        public void onChanged(List<Journal> list) {
            journalAdapter.submitList(list);
        }
    });
}

BookmarksFragment.java

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    JournalFactory factory = new JournalFactory(requireActivity().getApplication());
    journalViewModel = new ViewModelProvider(requireActivity(), factory).get(JournalViewModel.class);
    journalViewModel.getBookmarkedJournals().observe(getViewLifecycleOwner(), new Observer<List<Journal>>() {
        @Override
        public void onChanged(List<Journal> list) {
            adapter.submitList(list);
        }
    });
}

但是,当我使用这种方法时,问题是当我删除某些Fragment中的某些更改时,例如删除或更新某些Journal,而其他Journal的日期字段则随机更改。

我能够通过使用单个LiveData对象并在两个片段中对其进行观察来解决此问题。我必须在BookmarkFragment中进行的更改如下:

BookmarksFragment.java

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    JournalFactory factory = new JournalFactory(requireActivity().getApplication());
    journalViewModel = new ViewModelProvider(requireActivity(), factory).get(JournalViewModel.class);
    journalViewModel.getAllJournals().observe(getViewLifecycleOwner(), new Observer<List<Journal>>() {
        @Override
        public void onChanged(List<Journal> list) {
            List<Journal> bookmarkedJournals = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getBookmark() == 1)
                    bookmarkedJournals.add(list.get(i));
            }
            adapter.submitList(bookmarkedJournals);
        }
    });
}

现在可以正常使用。

但是,我想知道为什么我的第一种方法无法使用,这是使用两个不同的LiveData对象并在不同的片段中对其进行观察。

不是要在单个ViewModel中使用多个LiveData对象吗?

OR

同一视图模型的两个实例在进行更改并同时从同一表中获取不同的LiveData对象时,不允许同时存在吗?

android android-fragments android-room android-lifecycle android-viewmodel
1个回答
0
投票

我已找出导致此问题的原因。

[当我使用LiveData和getViewLifecycleOwner()作为LifecycleOwner时,我作为参数传递的观察者从未被移除。因此,切换到另一个选项卡后,有两个活动的观察者观察同一ViewModel的不同LiveData对象。

解决此问题的方法是将LiveData对象存储在变量中,然后在切换到其他片段时删除观察者。

在我的情况下,我通过以下操作解决了这个问题:

//store LiveData object in a variable
LiveData<List<Journal>> currentLiveData = journalViewModel.getAllJournals();

//observe this livedata object
currentLiveData.observer(observer);

然后以适当的生命周期方法或适合您需求的任何位置删除此观察器,例如

@Override
public void onDestroyView() {
    super.onDestroyView();

    //if you want to remove all observers
    currentLiveData.removeObservers(getViewLifecycleOwner());

    //if you want to remove particular observers
    currentLiveData.removeObserver(observer);
}
© www.soinside.com 2019 - 2024. All rights reserved.