如何使用 MutableList<String> 支持 MutableList<Uri> 字段

How to back a MutableList<Uri> field with a MutableList<String>

我有一个看起来像这样的界面:

interface MyObject {
    val id: String
    val media: MutableList<Uri>
}

我想在媒体列表由 MutableList<String> 而不是 MutableList<Uri> 支持的情况下实现它(我需要的原因在我的长问题 here).简单的方法是:

data class MyObjectPojo(
    override val id: String,
    val mediaStringList: MutableList<String>
) : Tale {
    override val media: MutableList<Uri>
        get() = mediaStringList.map { Uri.parse(it) } as MutableList<Uri>
}

但这显然是低效的(例如,为了只获取第一个元素,映射操作将 运行 用于整个列表)。我考虑过 get() = object : MutableList<Uri> {...},但我意识到我必须实现超过 20 个成员...有没有更好的方法来实现它?

一种选择是扩展 AbstractList,这可以很简单:

val media = object : AbstractList<URL>() {
    override val size get() = mediaStringList.size
    override fun get(index: Int) = Uri.parse(mediaStringList[index])
}

这为您提供了底层 mediaStringList 的只读视图:对其所做的任何更改都会立即反映在视图中。

与大多数性能问题一样,这是一种权衡:它本身不存储任何数据,但每次检索项目时都需要创建一个新的 Uri。因此,只有当您需要以额外处理为代价来节省内存时,这是一个好主意;或者当列表与检索到的项目数相比可能很大时。

如果您希望视图可写,您可以改为扩展 AbstractMutableList,并覆盖另外三个方法。 (留作练习:-)

PS。我建议 initialising media 这个对象,而不是在 getter 中创建它,因为后者会在每次 [=33] 时创建一个新视图=] 被调用,这是浪费。 (如果您担心为每个 MyObjectPojo 创建一个视图,您可以将其包装在 by lazy {…} 中,这样它只会在第一次需要时创建——以一些同步为代价。 )