【问题标题】:How can I loop over an array of sets/maps with varying data types如何遍历具有不同数据类型的集合/映射数组
【发布时间】:2021-12-09 23:15:45
【问题描述】:

我想让我的代码保持干爽,并创建 3 个(或更多或更少)结构大致相同的按钮。因此,我创建了一个要循环的对象列表,并将数据放入对象中,以便在 AppButton 的多个位置使用。

我可能觉得有点过于 Pythonic,因为那是我的主要语言,而且我最近才开始使用 Kotlin。我通常在 Python 中做的事情:

app_buttons = [
    dict(
        text="....",
        icon="....",
        uri_string="....",
    ),
    ...
]

我用mapOf 在 Kotlin 中尝试过类似的东西:

val appButtons = arrayOf(
    mapOf(
        "title" to getString(R.string.app_btn_example1),
        "icon" to R.drawable.ic_some_icon_1_64,
        "uriString" to "myapp://example1",
    ),
    ...
)

然后遍历它们并从地图中获取:

for (entry in appButtons) {
    buttons.add(
        AppButton(
            entry.get("text"),
            entry.get("icon"),
        ) {
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.get("uriString"))).apply {
                val name = getString(R.string.saved_account_key)
                putExtra(name, sharedPref.getString(name, null))
            }
            startActivity(intent)
        }
    )
}

然后我得到Type mismatch. Required String. Found {Comparable & java.io.Serializable}?。我不知道该放什么类型...

好的不同的方法,使用setOf 和解构:

val appButtons = arrayOf(
    setOf(
        getString(R.string.app_btn_example1),
        R.drawable.ic_some_icon_1_64,
        "myapp://example1",
    ),
    ...
)

for ((text, icon, uriString) in appButtons) {
    buttons.add(
        AppButton(
            text,
            icon
        ) {
            ...
        }
    )
}

但现在我得到以下信息:

Set & java.io.Serializable}> 类型的解构声明初始化器必须有一个“component1()”函数

Set & java.io.Serializable}> 类型的解构声明初始化器必须有一个“component2()”函数

Set & java.io.Serializable}> 类型的解构声明初始化器必须有一个“component3()”函数

我该如何进行这项工作?如何创建对象的基本列表并使用正确的类型循环它们?在 Python 中感觉很简单。我显然错过了一些东西。

【问题讨论】:

  • 请不要以这种方式使用地图。创建一个名为 ButtonModel 或类似名称的数据类。
  • @Sweeper 是的,这就是我问的原因。我觉得我做错了什么,但我不知道应该怎么做。
  • Kotlin(无论如何在 JVM 上)是一种静态类型语言(其中类型,IntString 等在编译时是已知的),Python 是动态类型的(类型在运行)。这使您可以创建基本上包含任何内容的dicts,并且由您来确保正确处理拉出的东西-您必须知道iconInt并将其视为一个,否则您将运行时崩溃。您不能(通常)在静态类型语言中这样做 - 它们强制正确使用类型,因此您不能将它们混合在地图中。像 Sweeper 的答案这样的数据结构就是你所需要的!

标签: kotlin


【解决方案1】:

您应该创建一个数据类,而不是使用地图。例如:

data class ButtonModel(
     val title: String,
     val icon: Int,
     val uriString: String,
)

然后您可以像这样创建数组:

val appButtons = arrayOf(
    ButtonModel(
        title = getString(R.string.app_btn_example1),
        icon = R.drawable.ic_some_icon_1_64,
        uriString = "myapp://example1",
    ),
    ...
)

如果您愿意,也可以不使用参数标签:

val appButtons = arrayOf(
    ButtonModel(
        getString(R.string.app_btn_example1),
        R.drawable.ic_some_icon_1_64,
        "myapp://example1",
    ),
    ...
)

那么,不用get[] 获取它们,您可以只使用点语法:

buttons.add(
    AppButton(
        entry.text,
        entry.icon,
    ) {
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(entry.uriString)).apply {
            val name = getString(R.string.saved_account_key)
            putExtra(name, sharedPref.getString(name, null))
        }
        startActivity(intent)
    }
)

【讨论】:

  • 在紧要关头,您可以为此使用Triple。但是自定义类更清晰、更安全、更易读。 (在 Kotlin 中定义也很快;它甚至可以是单行的!)
猜你喜欢
  • 2014-08-13
  • 2019-03-17
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2022-11-07
相关资源
最近更新 更多