Несколько объектов LiveData в одной ViewModel - PullRequest
2 голосов
/ 28 апреля 2020

Структура моей заявки следующая:

  • MainActivity (Activity) containing Bottom Navigation View with three fragments nested below
    • HomeFragment (Fragment) containing TabLayout with ViewPager with following two tabs
      • Журнал (Fragment)
      • Закладки (Fragment)
    • Фрагмент B (Fragment)
    • Фрагмент C(Fragment)

Я использую Room для ведения всех записей журналов. Я наблюдаю один объект 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;
    }
}

Я создаю экземпляр этой ViewModel внутри onActivityCreated() метода обоих фрагментов.

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? ?

ИЛИ

Разрешено ли двум экземплярам одного и того же ViewModel существовать вместе при внесении изменений и одновременном извлечении различных объектов LiveData из одной таблицы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...