Запуск обновления для члена LiveData при обновлении другой LiveData в модели представления

В приложении для игры в слова я делю модель между действием и фрагментом:

public class MainViewModel extends AndroidViewModel {
    private LiveData<List<Game>> mGames;
    private final MutableLiveData<Game> mDisplayedGame = new MutableLiveData<>();

(прошу прощения за неанглийский текст на скриншоте)

Деятельность наблюдает mGames в данный момент воспроизводится пользователем и обновляет меню навигационного ящика (см. левую часть приведенного выше снимка экрана).

Фрагмент наблюдает mDisplayedGame и отображает его в пользовательском представлении (см. правую часть скриншота выше).

Моя проблема в том, что, когда список игр обновляется на сервере (и действие получает новый список игр через Websocket и сохраняет его в комнате), мне нужно опубликовать обновление фрагмента: "Эй, игра, которую вы отображаются обновления, перерисовать его!

Возможно ли это сделать из модели общего представления?

Я знаю, что я мог наблюдать mGames и во фрагменте добавьте туда код, перебирая их, а затем выясняя, обновлялась ли отображаемая игра на сервере.

Но я бы предпочел сделать это в MainViewModel потому что у меня есть ощущение, что фрагмент должен наблюдать только за той игрой, которую он показывает, и все.

TL; DR

Всякий раз, когда mGames обновляется в виде модели через Room, мне нужно уведомить mDisplayedGame наблюдатели тоже!

2 ответа

Решение

Вы должны использовать MediatorLiveData для этого.

Как это работает, так это

public class MainViewModel extends AndroidViewModel {
    private final LiveData<List<Game>> mGames;
    private final MutableLiveData<Game> mSelectedGame = new MutableLiveData<>();

    private final MediatorLiveData<Game> mDisplayedGame = new MediatorLiveData<>();

    {
        mDisplayedGame.addSource(mGames, (data) -> {
            // find the new value of the selected game in the list
            mSelectedGame.setValue(newSelectedGame);
        });

        mDisplayedGame.addSource(mSelectedGame, (data) -> {
            mDisplayedGame.setValue(data);
        });
    }

А потом ты выставляешь mDisplayedGame как LiveData<Game> и это должно просто работать.

Используйте callback bro - добавьте интерфейс обратного вызова в вашей viewmodel и метод setCallback - сделайте так, чтобы ваш фрагмент реализовал его, затем вызовите viewmodel.setCallback(фрагмент) - вызовите обратный вызов в вашем наблюдателе