2017-10-10 60 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