【问题标题】:How to declare a property which will be lately initialized in Kotlin?如何声明一个最近将在 Kotlin 中初始化的属性?
【发布时间】:2019-09-30 11:27:35
【问题描述】:

如何在 MainActivity 中为 ListView 设置我的 ArrayAdapter 全局?

我的代码是:

class MainActivity : AppCompatActivity() {

var listItems = ArrayList<String>()
private var listAdapter: ArrayAdapter<String>? = null


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)

    listAdapter = ArrayAdapter(
        this,
        android.R.layout.simple_list_item_1,
        listItems
    )
    listfield.adapter = listAdapter
    listAdapter.add("Hello World!")
    listAdapter.add("RFID app")

所以问题是这会在编译时出错: 智能转换为 ArrayAdapter 是不可能的,因为 'listAdapter' 是一个可变属性,此时可能已更改。 这是因为在调用 .Add 时无法知道另一个线程是否将 listAdapter 设置回 null。

我需要 listAdapter 是全局的,因为我需要从回调函数调用 .notifyDataSetChanged() (当条形码阅读器读取条形码时),如果我在 onCreate() 中声明 listAdapter 它是不可用于回调函数。所以它必须是一个属性。 Kotlin 抱怨一个属性必须要么被初始化要么被声明为“抽象”。显然“抽象”在这里不起作用,但我不能将它初始化为“null”以外的其他东西,因为初始化需要上下文并且上下文在 onCreate() 之前不可用。 在 Kotlin 中如何解决这个问题?

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    更好的方法是将listAdapter 声明为lateinit

    改成:

    private lateinit var listAdapter: ArrayAdapter<String>
    

    【讨论】:

    • 我认为 OP 希望 listAdapter 对其他类也全局可用,但这个答案是正确的:P
    • 这对我来说非常有效。谢谢!我意识到在这里使用“全局”这个词是不正确的,因为我可以使用 private 修饰符。我只需要它对 MainActivity 中的 onCreate 以外的其他函数可用。
    【解决方案2】:

    发生这种情况是因为 Kotlin 无法判断该属性是否为 null,您有两种选择来修复错误:

    1. 添加!!运算符,如果变量为null,将抛出错误,例如:listAdapter!!.add("Hello World!")
    2. 使用lateinit 选项。此选项更好,因为在您的情况下,适配器永远不能为空。

    【讨论】:

    • 感谢您提供有关 !!选项,虽然我选择了lateinit
    • 在这种情况下,lateinit 是要走的路,在其他情况下,当您处理可空值时,运算符 !!? 是要走的路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-30
    • 1970-01-01
    • 2023-01-26
    相关资源
    最近更新 更多