首页 > 解决方案 > 在视图模型中更新另一个 LiveData 时触发 LiveData 成员的更新

问题描述

在一个文字游戏应用程序中,我在活动和片段之间共享一个模型:

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

(请原谅截图中的非英文文字)

活动和片段

Activity观察mGames用户当前正在播放的内容并更新导航抽屉菜单(参见上面屏幕截图的左侧)。

片段在自定义视图中观察mDisplayedGame并显示它(参见上面屏幕截图的右侧)。

我的问题是,当游戏列表在服务器上更新时(并且活动通过 Websocket 接收新的游戏列表并将其存储在房间中),我需要将更新发布到片段:“嘿,你的游戏正在显示已更新,重绘它!”

是否可以从共享视图模型中做到这一点?

我知道我也可以mGames在片段中观察并在其中添加代码迭代它们,然后找出显示的游戏是否在服务器上更新。

但我更喜欢在 中这样做,MainViewModel因为我有一种感觉,片段应该只观察它正在显示的一个游戏,仅此而已。

TL;博士

每当mGames通过 Room 在视图模型中更新时,我也需要通知mDisplayedGame观察者!

标签: androidviewmodelobserver-patternandroid-architecture-componentsandroid-livedata

解决方案


您应该为此使用 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为 a LiveData<Game>,它应该可以工作。


推荐阅读