Ошибка переменной Lateinit, не инициализированной, но инициализированной (android)

#java #android #arrays #kotlin

#java #Android #массивы #kotlin

Вопрос:

Я знаю, это звучит странно. Итак, в моей MainActivity я объявляю массив объекта SongInfo , который выглядит следующим образом:

 class SongInfo {
    lateinit var title: String
    lateinit var contentId: String
    lateinit var filepath: String
}
  

Вот как я объявляю массив в своей MainActivity:

 lateinit var songInfo: Array<SongInfo?>
  

Итак, теперь, когда я нажимаю кнопку, слушатель этой кнопки выполняет это:

 searchButton.setOnClickListener {
            val cursor = contentResolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                arrayOf(
                    "_id",
                    "_data",
                    MediaStore.Audio.Media.TITLE,
                    MediaStore.Audio.Media.ARTIST,
                    MediaStore.Audio.Media.DURATION
                ),
                "is_music == 1",
                null, null
            )

            songInfo = arrayOfNulls(cursor!!.count)

            for (index in songInfo.indices) {
                songInfo[index] = SongInfo()
                Log.d(tag, "searchButton: $index")
            }

            adapter = listMusicService.listMusic(cursor)
            adapter.notifyDataSetChanged()
        }
  

ListMusicService Класс выглядит следующим образом:

 class ListMusicService(val context: Context, private var adapter: ArrayAdapter<Any>) {

    private val tag = "MusicShare/ListMusicService"

    fun listMusic(cursor: Cursor): ArrayAdapter<Any> {
        val activity = MainActivity()
        adapter.clear()

        val songInfo = arrayOfNulls<SongInfo>(cursor.count)

        var duration: Double

        var index = 0

        while (cursor.moveToNext()) {
            duration = ((cursor.getDouble(4) / 600).roundToInt() / 100).toDouble()

            adapter.add(cursor.getString(3)   ": "   cursor.getString(2)   " ("   duration   ")")

            val filepath = File(cursor.getString(1))

            Log.d(tag, "searchMusic: writing songInfo")

            songInfo[index] = SongInfo()

            songInfo[index]!!.title = filepath.name
            songInfo[index]!!.filepath = filepath.absolutePath
            activity.songInfo[index]!!.filepath = filepath.absolutePath
            songInfo[index]!!.contentId = cursor.getString(0)

            index  
        }

        return adapter
    }
}
  

Нажатие searchButton сейчас вызывает kotlin.UninitializedPropertyAccessException: lateinit property songInfo has not been initialized .
Но я не понимаю, почему, потому что в методе listener searchButton я инициализирую каждый объект массива. Кто-нибудь знает, почему это происходит, и, возможно, что идет не так?

РЕДАКТИРОВАТЬ: создание ListMusicService :

 val listMusicService = ListMusicService(this, adapter)
  

Ответ №1:

Вы создаете новый объект MainActivity

 val activity = MainActivity()
  

это просто пустой объект, вместо этого вам нужно передать this в качестве экземпляра MainAcitiy listMusic метода to и использовать его.


ListMusicService класс уже принимает context объект, поэтому кажется, что вы передаете экземпляр activity (без кода об этом), используйте существующий экземпляр адаптера MainAcitivty .

 // somewhere in main activity 
val listMusicService = ListMusicService(this, adapter)

// inside searchButton.setOnClickListener
adapter = listMusicService.listMusic(cursor)
adapter.notifyDataSetChanged()
  

В ListMusicService

 fun listMusic(cursor: Cursor): ArrayAdapter<Any> {
    adapter.clear()
    val songInfo = arrayOfNulls<SongInfo>(cursor.count)

    var duration: Double

    var index = 0

    while (cursor.moveToNext()) {
        duration = ((cursor.getDouble(4) / 600).roundToInt() / 100).toDouble()

        adapter.add(cursor.getString(3)   ": "   cursor.getString(2)   " ("   duration   ")")

        val filepath = File(cursor.getString(1))

        Log.d(tag, "searchMusic: writing songInfo")

        songInfo[index] = SongInfo()

        songInfo[index]!!.title = filepath.name
        songInfo[index]!!.filepath = filepath.absolutePath
        activity.songInfo[index]!!.filepath = filepath.absolutePath
        songInfo[index]!!.contentId = cursor.getString(0)

        index  
    }
    return adapter
}
  

Комментарии:

1. Ну, как именно мне нужно передать ее, чтобы я мог получить доступ к SongInfo массиву в ListMusicService

2. @shuzo можете ли вы обновить свой пост о том, как вы создаете экземпляр ListMusicService класса, хотя я добавляю код решения в середине.

3. @shuzo как и ожидалось, следуйте опубликованному коду и дайте мне знать.

4. Большое вам спасибо за вашу помощь. Теперь он работает полностью!

5. @shuzo С удовольствием. Ознакомьтесь с обновленным кодом. У класса MusicService уже есть адаптер, поэтому используйте его напрямую. Если вы не хотите создавать новый объект адаптера в mainactivity, вы можете даже удалить возвращаемый экземпляр адаптера и добавить adapter.notifyDataSetChanged() в конце listMusic метода. context.adapter требуется только в том случае, если вы воссоздаете объект адаптера MainActivity . Счастливого кодирования!