Запуск обновления для члена 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(фрагмент) - вызовите обратный вызов в вашем наблюдателе