0

There is processing to acquire the image held by android using the cursor.The cursor needs authorization to external storage. If AndroidOS is 6.0 or higher and authorization permission is not obtained, the application will be terminated. If permission is obtained, processing to close the cursor is necessary.

If it is Java, it would have been nice to write to onStop as follows, except for Kotlin, an exception will be raised.

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

kotlin.UninitializedPropertyAccessException: lateinit property cursor has not been initialized

So I wrote that we initialize the cursor and finish it.

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

This no longer causes an exception, but it seems that you write unnecessary code, and it does not get clearer. However, I do not lateinit the cursor, and I think that it is useless code to initialize it at the time of declaration. Also, when declaring private var cursor: Cursor? = Null, I think that a null judgment code is necessary in various places and I do not think it is like Kotlin.

I would be pleased if you could give me advice on how to write the best.

This is the code that is used:

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()
}
Axel
  • 3,331
  • 11
  • 35
  • 58
  • Did you check [this question](https://stackoverflow.com/questions/36623177/kotlin-property-initialization-using-by-lazy-vs-lateinit) – Teocci Oct 10 '17 at 01:40

2 Answers2

1

No, this is not the best use of lateinit. First, the use of lateinit is for a variable that should be available when it is being used. Using nullable mean the variable can be null which is different for lateinit meaning it should not be null.

It is pretty useful in Android as you initial variable in onCreate instead of constructor. It is also good for dependency injection likke Dagger.

It throws of UninitializedPropertyAccessException mean your Cursor is not initialized when it is being access. That's mean there is a logical error in your code that the cursor being access without initialize.

Note that hold a Cursor is not a good practice. It holds a connection to the database. You should close after using it and recreate a new one instead of holding it.

Joshua
  • 5,901
  • 2
  • 32
  • 52
  • Thank you for your reply. I understand your answer, but from your answer, I did not know the alternative way.I think that using nullable method(like Cursur?) is not like kotlin. – ohtakazuki Oct 10 '17 at 13:35
0

Use lateinit for properties that cannot be initialized in a constructor

Gulzar Bhat
  • 1,255
  • 11
  • 13