【问题标题】:Is the best way using lateinit?使用lateinit的最好方法是什么?
【发布时间】:2018-03-21 06:52:54
【问题描述】:

有处理使用游标获取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()
}

【问题讨论】:

标签: android kotlin


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    它在 Android 中非常有用,因为您在 onCreate 中使用初始变量而不是构造函数。就像 Dagger 一样,它也适合依赖注入。

    它抛出UninitializedPropertyAccessException 意味着您的Cursor 在访问时未初始化。这意味着您的代码中有一个逻辑错误,即光标在没有初始化的情况下被访问。

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

    【讨论】:

    • 感谢您的回复。我理解你的回答,但从你的回答中,我不知道替代方法。我认为使用可为空的方法(如 Cursur?)不像 kotlin。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 2017-10-18
    • 2018-07-06
    相关资源
    最近更新 更多