英文:
Lateinit variable not initialized error but got initialized (android)
问题
我知道这听起来很奇怪。
所以在我的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
。但我不明白为什么会这样,因为在searchButton
的监听方法中,我正在初始化数组中的每个对象。是否有人知道为什么会出现这种情况,以及可能出了什么问题?
编辑:创建ListMusicService
:
val listMusicService = ListMusicService(this, adapter)
英文:
I know that sounds weird.
So in my MainActivity am declaring an Array of the object SongInfo
which looks like this:
class SongInfo {
lateinit var title: String
lateinit var contentId: String
lateinit var filepath: String
}
This is how I am declaring the Array in my MainActivity:
lateinit var songInfo: Array<SongInfo?>
So, now when I press a button, the listener of this button executes this:
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()
}
The ListMusicService
class looks like this:
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
}
}
Pressing the searchButton
now causes a kotlin.UninitializedPropertyAccessException: lateinit property songInfo has not been initialized
.
But I don't understand why because in the listener method of searchButton
I'm initializing every object of the array. Does anybody know why this happens and maybe what goes wrong?
EDIT: Creating the ListMusicService
:
val listMusicService = ListMusicService(this, adapter)
答案1
得分: 1
你正在创建一个新的 MainActivity
对象:
val activity = MainActivity()
这只是一个空对象,而你实际上需要将 this
作为 MainActivity
的实例传递给 listMusic
方法并使用它。
ListMusicService
类已经接受一个 context
对象,所以看起来你正将活动的实例传递给了它(没有相关的代码),你应该使用 MainActivity
的现有适配器实例。
// 在主活动的某处
val listMusicService = ListMusicService(this, adapter)
// 在 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
}
英文:
You are creating a new object of MainActivity
val activity = MainActivity()
which is just an empty object, instead you need to pass this
as an instance of MainAcitiy
to listMusic
method and use it.
ListMusicService
class already taking a context
object so seems like you are passing the activity's instance (no code about it), use the existing adapter instance of MainAcitivty
.
// somewhere in main activity
val listMusicService = ListMusicService(this, adapter)
// inside searchButton.setOnClickListener
adapter = listMusicService.listMusic(cursor)
adapter.notifyDataSetChanged()
In 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论