首页 > 解决方案 > 如何正确清理使用 RX 从服务器接收到的项目列表 | 过滤{}地图{}

问题描述

我有以下代码,我试图将其用于两个目的:

1) 调用 API 并以 POJO 形式获取结果

2) 在 UI 中显示此对象 (POJO) 之前对其进行清理

   private fun getWinbackDataItems(rewardPurpose: String) /*Single<WinbackBaseItem>*/ {
        val x = repository.getRewardsList(rewardPurpose)
            .filter {
                it.result?.rewards != null
            }.map { winback ->
           winback.result?.rewards?.asSequence()?.filter { rewardsItem ->
                rewardsItem?.id != null && rewardsItem.title != null
            }?.toList()?.take(3)?.map {
                WinbackListItem(it?.id, it?.title!!, false)
            }?.toList()
        }
    }

对我来说,争论的焦点是下面一行:

 itemListSanitized.add(WinbackListItem(it.id, it.title, false))

在这一点上,我假设过滤器已经从原始列表中删除了所有空值,但令我惊讶的是,我发现我必须在将它们添加到新列表时对其及其所有内容进行空值检查。

我在这里想念什么,请原谅我的天真,因为我刚刚开始反应

标签: kotlinrx-java

解决方案


我认为您的工作不是针对执行代码,而是针对您的 IDE 的警告消息,或者只是针对此代码的编译能力。您可能遇到的是,早期的检查null不一定允许编译器稍后假定非空值,因为与此同时,不同线程中的其他代码可能已经运行并更改了值。

因此,当您创建 WinbackListItem 时,您可以安全地假设某些项目不为空,但编译器无法确定这一点,因为它无法知道您的进程空间中还发生了什么。所以编译器要求你告诉它不要担心空值(!!)或者你再次检查这些值。这正是 Kotlin 的工作方式。它通常是 PITA,但事实就是如此。

我使用发布的代码只是为了确保我知道我在说什么。这是我能够运行的代码:

private fun getWinbackDataItems(rewardPurpose: String) /*Single<WinbackBaseItem>*/ {
    val x = repository.getRewardsList(rewardPurpose)
        .filter {
            it.result?.rewards != null
        }.map { winback ->
            winback.result?.rewards?.asSequence().filter { rewardsItem ->
                rewardsItem.id != null && rewardsItem.title != null
            }.toList().take(3).map {
                println(it.id)
                println(it.title)
                WinbackListItem(it.id!!, it.title!!, false)
            }.toList()
        }.count()
}

我创建了一些非常简单的类和对象来满足这段代码并让它运行。请注意,我取出了一些不必要的“?” 空检查。我一直在使用输入值,直到我确信it.id并且it.title永远不会null在调用 WinbackListItem 构造函数时。然而,鉴于 WinbackListItem 的此定义不接受参数值,因此需要!!其参数上的两个或其他确保它们不是的东西:nullnull

class WinbackListItem(val id: Int, val title: String, val huh: Boolean)

推荐阅读