ViewModel, LiveData and Transformations.map

8

我刚接触 Kotlin 和 Android 开发,不太确定如何应用业务逻辑并转换值。我有一个类的列表,并且想要修改该类中的某个值,同时不影响该类中的其他内容。但是一旦到达 ViewModel,我不确定如何访问我的类中的时间值以进行修改。如果有人能指点我正确的方向,我将不胜感激。

实体和 Dao

import org.threeten.bp.Instant

data class ActionDetails(val time: Instant,
                     val firstName: String,
                     ... )

@Query("SELECT time, first_name as firstName...")
fun liveStatus(): LiveData<List<ActionDetails>>

视图模型

class MainViewModel(private val repository: DataRepository) : ViewModel() {

    private val _actions: LiveData<List<ActionDetails>>
    val actions: LiveData<List<ActionDetails>>
        get() = _actions

    init {
        _actions = Transformations.map(repository.liveStatus()) {
            //Convert Instant value per business rules and convert to formatted string
            time -> ...

        }
    }
}
1个回答

8
你不能只改变一个值。创建一个新的数据类,代表经过业务逻辑转换后的完整对象。
例如,从
data class ActionDetails(val time: Date, val firstName: String, val lastName: String)

to

data class DisplayItem(val time: String, val firstName: String, val lastName: String, val fullName: String)

然后将您的LiveData从List<ActionDetails>转换为List<DisplayItem>。为此,您可以使用Iterable#map函数,该函数对列表的每个元素应用转换并返回结果列表。

Transformations.map(repository.liveStatus()) { list ->
    list.map { item ->
        val formattedTime = item.time.toString() // whatever you need
        val fullName = "${item.firstName} ${item.lastName}"
        DisplayItem(formattedTime, item.firstName, item.lastName, fullName)
    }
}

顺便说一下:如果只是想改变一个小细节,也许不需要使用Transformations.map,而是在显示字符串的地方直接进行格式化,例如在适配器视图持有者中。


谢谢你的参与和相关细节,我没有意识到我需要构建一个新列表。虽然我考虑过在数据绑定中格式化结果,但我不想把所有的代码都放在XML中。我会尝试一下这个方法,并重新评估我的选择。 - Bink
在进一步思考后,我可以在数据类中添加一个函数来处理此值的格式,并从布局中的数据绑定调用该函数。这将使代码脱离XML文件,但我不确定这种方法是否比转换更好。有任何看法吗? - Bink
1
@Bink 对于任何一种选项都没有太大的优势。据我所知,转换仅在实时数据更新时运行一次,这可能会对列表视图的平滑滚动产生影响,例如当您有时可以感觉到正在动态处理项目时。但是,格式化日期字符串并不重要,因此,任何一种方式都应该可以正常工作。 - zapl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接