【问题标题】:Efficient Transformations of LiveData<List> to another LiveData<List>LiveData<List> 到另一个 LiveData<List> 的高效转换
【发布时间】:2020-08-21 21:19:07
【问题描述】:

考虑存储在 Room db 中的一些通用 @Entity User。一些@Dao 重新运行LiveData&lt;List&lt;User&gt;&gt; aka 'dao 结果'。我希望创建另一个 live 列表,其中每个元素都是 dao 结果的转换,比如

LiveData<List<UserWrapper>>

//UserWrapper needs a User to construct

所以我写了类似的东西

 Transformations.map(daoResult,list -> {

            
            List<UserWrapper> newList=new ArrayList<>(list.size());
            list.forEach(user -> {
               newList.add(new UserWrapper(user));
            });

            return newList;
        });

如果我对 LiveData 的理解是正确的,dao 结果只响应List 级别的变化,比如列表被添加,被减去等等,而不是如果底层的 User 对象或者它的字段发生了变化。

  1. 这是正确的吗?

假设在 db 中进行了一些更改,这些更改使一些新记录有资格出现在底层 dao 结果的@Query的结果集中

  1. 查询结果LiveData&lt;List&lt;User&gt;&gt; 会自动反映这一点吗? Transformations.map 会把它带到LiveData&lt;List&lt;UserWrapper&gt;&gt; 吗?

在上述实现中,每次修改底层 list 时,地图都会创建一个新 List 并重新初始化它,这在我看来似乎效率低下和错误。为什么必须手动检查两个列表以确保一致的转换状态?

  1. 有没有更好的方法来做到这一点,使Users 和UserWrappers 之间始终保持一对一的对应关系?

【问题讨论】:

    标签: android list android-room android-livedata


    【解决方案1】:

    我不确定我是否明白你的问题的重点,但请考虑一下我的想法:

    1. 当您使用 LiveData 作为查询的返回类型时,Room 会为您设置某种回调。因此,如果您在查询中使用select * from users ...,则对表users 的每次更改都会触发更新LiveData 的值(这并不明显,所以我的意思是-每次更改,即使某些用户已更改但不在您的结果列表中) .
    2. 理论上,您可以从查询到表user,不仅List&lt;User&gt;,还可以List&lt;UserWrapper&gt;。这取决于UserWrapperUser 结构。为此,您应该编写一个与UserWrapper 字段匹配的字段的查询,或者使用Room's Relations

    【讨论】:

    • 所以如果我在表中有一个用户并说它的名称列在表中发生了变化,我的列表中User的相应名称字段会自动更新而无需重新获取?
    • 确切地说 - 在 db 表中更改用户名后,如果 - LiveData 有观察者(在活动中使用 observe() 方法或使用 Transformation.map/switchmap),所有附加的 LiveData 值都将更新。因此,例如,如果您在 observe() 方法中将用户的列表设置为 Recyclerview 的适配器 - 您将在那里看到更新的名称。是的,不需要重新获取 LiveData。
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多