【问题标题】:Combine two LiveData<Int> into one LiveData<List<Pair<Int, Int>>>将两个 LiveData<Int> 合并为一个 LiveData<List<Pair<Int, Int>>>
【发布时间】:2020-11-10 11:06:06
【问题描述】:

我想显示一个点图,其中点的卡路里消耗为 x 坐标,消耗的卡路里为 y 坐标。我在 ViewModel 中检索了两个卡路里,但我想将它们组合成一个 LiveData&lt;List&lt;Pair&lt;Int, Int&gt;&gt;&gt;。这样我就可以在我的片段中观察这个 LiveData 并访问具有 x 和 y 坐标(卡路里)的 Pairs 列表。

这是我的 DAO,我有两个 List&lt;Int&gt; 类型的 liveData:

@Query("SELECT amount from calories_table WHERE strftime('%m-%d-%Y', timestamp, 'unixepoch') IN (SELECT strftime('%m-%d-%Y', timestamp, 'unixepoch') FROM running_table)")
fun getCaloriesConsumedOnRunDays(): LiveData<List<Int>>

@Query("SELECT caloriesBurned FROM running_table")
fun getCaloriesFromRuns():LiveData<List<Int>>

这是我的仓库:

fun getCaloriesConsumedOnRunDays() = runDao.getCaloriesConsumedOnRunDays()

fun getCaloriesFromRuns() = runDao.getCaloriesFromRuns()

最后,我在 ViewModel 中创建了这两个变量来存储两个 liveData:

private val getCaloriesConsumedOnRunDays = mainRepository.getCaloriesConsumedOnRunDays()

private val getCaloriesFromRuns = mainRepository.getCaloriesFromRuns()

【问题讨论】:

    标签: kotlin android-livedata mutablelivedata


    【解决方案1】:

    首先,这是您的第一个问题,欢迎。

    您尝试执行的操作有两种方法。

    1. 这是特定于您正在尝试执行的操作...我建议在单个 SQLite 查询调用中提取所有数据,这将是更有效的方法。 SQLite 以 C 级速度运行,您宁愿让它完成所有繁重的工作,而不是在 VM 上使用 Kotlin 编写胶水代码。 (另外,将避免使用子选择,如果你只是在做WHERE .. IN;那么没有理由在他们周围做strftime,因为你只是想直接匹配)。

    这可能与您的想法有所不同,但是是这样的:

    @Query("""
    SELECT calories_table.amount, running_table.caloriesBurned 
    FROM calories_table 
    INNER JOIN running_table ON calories_table.timestamp = running_table.timestamp")
    """
    fun getCaloriesConsumedOnRunDays(): LiveData<List<Pair<Int, Int>>>
    

    (如果 ROOM 预编译器不喜欢在那里有 Pair&lt;Int, Int&gt;,请创建一个新的数据类,例如 data class CaloriesInfo(val amount: Int, val caloriesBurned: Int) 并将其用作您的返回数据类型)

    这样你只需要一个 LiveData。

    1. 有时您可能需要将两个或多个 LiveData 合并在一起的合法用例,在这种情况下您应该使用 MediatorLiveData

    类似:

    val mediator: MediatorLiveData<Pair<Int, Int>> = MediatorLiveData()
    
    val liveData1 = repo.getLiveData()
    val liveData2 = repo.getAnotherLiveData()
    
    mediator.addSource(liveData1) { mediator.postValue(it to liveData2.value) }
    mediator.addSource(liveData2) { mediator.postValue(liveData1.value to it) }
    

    有时这样做有充分的理由,但我不建议您这样做,因为您需要做其他事情才能以正确的格式获取数据对您绘图很有用。 LiveData 异步运行,因此当您尝试绘制内容时,x 和 y 来自不同的 LiveData 没有意义。你最好的选择仍然是做一个更好的 SQLite 查询并在一个查询中完成。

    【讨论】:

    • 谢谢比利的回答。我尝试了第一个选项,因为它对我的问题更有意义。 ROOM 预编译器有 Pair 的问题,所以我只使用了自定义数据类。
    猜你喜欢
    • 2010-12-09
    • 2020-10-22
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多