【问题标题】:Android MVVM - Update ViewModel when data changesAndroid MVVM - 数据更改时更新 ViewModel
【发布时间】:2019-08-14 10:42:03
【问题描述】:

我正在开发一个使用MVVM 模式和RxJava 的应用程序。架构如下:

这是我第一次使用这种模式,我不确定当数据发生变化时更新ViewModel(以及相应的View)的最佳方法是由另一个组件进行的应用。

例如:假设我们有一个 Activity 显示我关注的用户列表(就像一个社交应用程序),我从这个列表中选择一个用户并在另一个 Activity 中打开他的个人资料。现在,从第二个Activity 开始,我决定取消关注该用户,当我按下后退按钮返回第一个Activity 时,我希望自动更新列表(删除相应的用户,显然无需重新下载所有数据)。

问题是这两个Activity 有两个不同的ViewModel。如何使第二个Activity 所做的更改影响第一个ViewModelRepository 是否有责任通知第一个 Activity 更改?

  • 我宁愿不使用startActivityForResult
  • 我宁愿不要将第一个ActivityViewModel 注入到第二个中

非常感谢!

【问题讨论】:

    标签: android mvvm kotlin rx-java


    【解决方案1】:

    我决定取消关注该用户,当我按下返回按钮返回第一个活动时,我希望列表自动更新(删除相应的用户,显然无需重新下载所有数据)。

    问题是两个Activity有两个不同的ViewModel。

    我以为您有一个存储库,其中包含能够公开 LiveData<*> 的“模型”(本地数据源),不是吗?

    在这种情况下,您需要做的就是:

    @Dao
    public interface ItemDao {
        @Query("SELECT * FROM ITEMS")
        LiveData<List<Item>> getItemsWithChanges();
    
        @Query("SELECT * FROM ITEMS WHERE ID = :id")
        LiveData<List<Item>> getItemWithChanges(String id);
    }
    

    现在您的存储库可以从 DAO 返回 LiveData:

    public class MyRepository {
        public LiveData<List<Item>> getItems() {
            // either handle "fetch if needed" here, or with NetworkBoundResource
            return itemDao.getItemsWithChanges();
        }
    }
    

    您在 ViewModel 中获得的内容:

    public class MyViewModel extends ViewModel {
        private final LiveData<List<Item>> items;
    
        public MyViewModel(MyRepository repository) {
            this.items = repository.getItems();
        }
    
        public LiveData<List<Item>> getItems() {
            return items;
        }
    }
    

    如果你观察到这一点,那么当你修改 Room 中的项目时,它会自动更新 onStart 中的这个 LiveData(当你再次开始观察时)。

    【讨论】:

    • 非常感谢,这正是我想要的!我主要需要调用远程 API,但我可以使用本地数据源作为一种缓存。
    • @EpicPandaForce 对于“getItemWithChanges(String id)”,我如何将 Activity 的 id 传递给 ViewModel 到 Repository,以便 Repository 返回“itemDao.getItemsWithChanges(String Id);”去道?
    • 我可能会把它传递给ViewModelProvider.Factory
    • 这不应该是公认的答案。在存储库中使用 Livedata 是一个坏主意的原因有很多。
    • 这篇文章基本上是在说“我们有一个带有 SQLite 的 DAO,我们仍然在代码中进行过滤,我们使用 Transformations.map {} 尽管它在 UI 线程上运行,但我们没有做任何事情应用多线程,现在我责怪 LiveData 没有按照我想象的方式工作”。这一切都通过switchMap { liveData { withContext(IO) { 解决,在撰写那篇文章时可用的,因此任何对“它在 UI 线程上运行”的呼吁实际上都无关紧要,因为它没有到。
    猜你喜欢
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    相关资源
    最近更新 更多