2017-10-10 84 views
0

正在进行处理以获取由android使用光标所持有的图像。光标需要授权到外部存储。 如果AndroidOS为6.0或更高版本且未获得授权许可,则应用程序将被终止。 如果获得许可,则需要关闭游标的处理。是使用lateinit的最佳方式吗?

如果是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() 
} 
+0

你检查了[这个问题](https://stackoverflow.com/questions/36623177/kotlin-property-initialization-using-by-lazy-vs-lateinit) – Teocci

回答

0

不,这不是lateinit物尽其用。首先,使用lateinit是为了在使用时应该可用的变量。使用可为空的变量可以是空的,这对于lateinit是不同的,这意味着它不应该为空。

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

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

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

+0

谢谢你的回复。我理解你的答案,但从你的回答中,我不知道替代方式。我认为使用可空方法(如Cursur?)不像kotlin。 – ohtakazuki