单个ViewModel中有多个LiveData对象



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

  • 主活动(Activity) containing Bottom Navigation View with three fragments nested below
    • 主页片段(Fragment) containing TabLayout with ViewPager with following two tabs
      • 期刊(Fragment)
      • 书签(Fragment)
    • 片段B(Fragment)
    • 片段C(Fragment)

我正在使用Room来维护日记账的所有记录。我在Journal和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;
}
}

我正在两个Fragments的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);
}
});
}

然而,当我使用这种方法时,问题是当我删除时,在任何片段中进行一些更改,比如删除或更新一些日志,其他日志的日期字段会随机更改。

我能够通过使用单个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对象并在不同的片段中观察它们。

多个LiveData对象是否不打算在单个ViewModel中使用?

在进行更改并同时从同一表中获取不同的LiveData对象时,是否不允许同一ViewModel的两个实例同时存在?

我找到了导致这个问题的原因。

当我使用带有getViewLifecycleOwner()作为LifecycleOwner的LiveData时,我作为参数传递的观察者从未被删除。因此,在切换到不同的选项卡后,有两个活动的观察者在观察同一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);
}

相关内容

  • 没有找到相关文章

最新更新