为什么从WeakReference.get()获取的类的非null类型属性更改为可为空

时间:2018-06-07 10:18:18

标签: android kotlin weak-references android-handler

我正在尝试在需要引用活动的Activity中编写Handler。如果我这样写

class MainActivity : AppCompatActivity() {
    private val mHandler = MainActivityHandler(this)

    class MainActivityHandler(val activity: MainActivity) : Handler() {
        override fun handleMessage(msg: Message?) {
            when(msg?.what) {
                MSG_CHANGE_TEXT -> {
                    activity.tv_logged.setText(R.string.title_main)
                    activity.mHandler.sendMessageDelayed(obtainMessage(SOMETHING), 3000)
                }
                // ...
            }
        }
    }
}

此代码按预期编译和工作。但是如果我尝试将弱引用传递给像这样的活动

class MainActivity : AppCompatActivity() {
    private val mHandler = MainActivityHandler(WeakReference(this))

    class MainActivityHandler(val activityRef: WeakReference<MainActivity>) : Handler() {
        private val activity
            get() = activityRef.get()

        override fun handleMessage(msg: Message?) {
            when(msg?.what) {
                MSG_CHANGE_TEXT -> {
                    activity?.tv_logged.setText(R.string.title_main)
                    activity?.mHandler.sendMessageDelayed(obtainMessage(SOMETHING), 3000)
                }
                // ...
            }
        }
    }
}

现在编译器抱怨 tv_logged mHandler 是可以为空的接收器类型,需要使用?进行访问。 我可以理解,处理程序中的val activity: MainAcitivity?是可以为空的,因为它来自WeakReference.get()但是MainActivity中的属性怎么也可以为空?

2 个答案:

答案 0 :(得分:1)

因为activity?.tv_logged的返回类型是(假设它是TextView),TextView? 。在Kotlin文档中,提出了通过null条件检查if的替代方案

  

您的第二个选项是安全通话操作员,写的?   B'。长度   如果b不为null,则返回b.length,否则返回null。这个表达式的类型是Int?

要仅针对非空值执行特定操作,您可以使用安全调用操作符和let:

 activity?.let{ //access activity via `it`}

答案 1 :(得分:0)

当我在https://kotlinlang.org/docs/reference/null-safety.html#safe-calls

阅读整篇文章时,我理解这一点

这与我怀疑的WeakReference无关。这是因为安全调用操作符即使在访问非可空类型属性时也返回可空类型。 (该文档并没有明确而明确地指明这一点。)