使用lateinit是最好的方法吗?

时间:2017-10-10 00:42:54

标签: android kotlin

有使用游标获取android所持有的图像的处理。游标需要授权给外部存储器。 如果AndroidOS为6.0或更高版本并且未获得授权许可,则应用程序将被终止。 如果获得了许可,则需要进行关闭光标的处理。

如果它是Java,那么按照以下方式写入onStop会很不错,除了Kotlin之外,还会引发异常。

if (cursor != null )
  cursor.close();

kotlin.UninitializedPropertyAccessException: lateinit property cursor has not been initialized

所以我写了我们初始化光标并完成它。

cursor = contentResolver.query(
    MediaStore.Images.Media.INTERNAL_CONTENT_URI,
    null, null, null, null
)

这不再导致异常,但似乎你编写了不必要的代码,并且它没有变得更清晰。 但是,我没有延迟光标,我认为在声明时初始化它是无用的代码。 此外,在声明private var cursor: Cursor? = Null时,我认为在各个地方都需要一个空判断代码,我认为它不像Kotlin。

如果你能就如何写出最好的作品给我建议,我会很高兴的。

这是使用的代码:

private lateinit var cursor : Cursor

private val PERMISSIONS_REQUEST_CODE = 100

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

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // Android Version 6.0 later
        if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            initCursor()
        } else {
            requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), PERMISSIONS_REQUEST_CODE)
        }
    } else {
        // Android Version under 6.0
        initCursor()
    }
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSIONS_REQUEST_CODE ->
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initCursor()
            } else {
                finishApp()
            }
        else ->
            finishApp()
    }
}

private fun finishApp() {
    //  It prevents kotlin.UninitializedPropertyAccessException of cursor(lateinit valiant). It's last resort...
    cursor = contentResolver.query(
            MediaStore.Images.Media.INTERNAL_CONTENT_URI,
            null, null, null, null)
    /*
    if(cursor != null)
        cursor.close()
    */
    finish()
}

override fun onStop() {
    super.onStop()
    cursor.close()
}

private fun initCursor() {
    cursor = contentResolver.query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null, null, null, null)
    cursor.moveToFirst()
}

2 个答案:

答案 0 :(得分:1)

不,这不是lateinit的最佳用法。首先,lateinit的使用是用于在使用时应该可用的变量。使用nullable意味着变量可以为null,这对于lateinit是不同的,这意味着它不应该为null。

它在Android中非常有用,因为您在onCreate而不是构造函数中初始变量。依赖注入也很有利于Dagger。

抛出UninitializedPropertyAccessException意味着您的Cursor在访问时未初始化。这意味着您的代码中存在逻辑错误,即光标无需初始化即可访问。

请注意,持有Cursor不是一个好习惯。它保存与数据库的连接。您应该在使用它之后关闭它并重新创建一个新的而不是保持它。

答案 1 :(得分:0)

lateinit用于无法在构造函数中初始化的属性