我声明了一个全局变量:
lateinit var trueBtn :Button
在activity的onCreate()函数中给它赋值
pos = (1..4).random() //生成正确单词释义的位置
withContext(Dispatchers.Main){
binding.apply {
when (pos) {
1 -> {
mean1.text = wordList[num].tranlation
trueBtn = mean1
}
2 -> {
mean2.text = wordList[num].tranlation
trueBtn = mean2
}
3 -> {
mean3.text = wordList[num].tranlation
trueBtn = mean3
}
4 -> {
mean4.text = wordList[num].tranlation
trueBtn = mean4
}
}
在onResume()函数中调用trueBtn的setOnClickListener函数实现功能,但是当我点击启动这一Activity闪退报错
显示:
java.lang.RuntimeException: Unable to resume activity {com.dyk.mysqltest/com.dyk.mysqltest.ui.LearnActivity}: kotlin.UninitializedPropertyAccessException: lateinit property trueBtn has not been initialized
为什么我已经在onCreate中赋值了,它依然报没有初始化的错误?
完整代码如下:
class LearnActivity : BaseActivity() {
var num = 0
lateinit var trueBtn :Button
val selectwords = selectWords()
private lateinit var wordList :MutableList<Word>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityLearnBinding.inflate(layoutInflater)
setContentView(binding.root)
var pos: Int //position四个选项的位置
lifecycleScope.launch(Dispatchers.IO) {
wordList = selectwords.select10words(this@LearnActivity)
binding.word.text = wordList[num].word
pos = (1..4).random() //生成正确单词释义的位置
withContext(Dispatchers.Main){
binding.apply {
when (pos) {
1 -> {
mean1.text = wordList[num].tranlation
trueBtn = mean1
}
2 -> {
mean2.text = wordList[num].tranlation
trueBtn = mean2
}
3 -> {
mean3.text = wordList[num].tranlation
trueBtn = mean3
}
4 -> {
mean4.text = wordList[num].tranlation
trueBtn = mean4
}
}
Log.d("BtnBindings","$pos")
}
}
val map = HashMap<Int, Int>()
for (i in 0..2) {
var randoms = getRandoms()
while (map.containsValue(randoms)|| wordList[0].id ==randoms.toLong()){
randoms = getRandoms()
}
map[i] = randoms
}
val othWords = mutableListOf<Word>()
for (i in 0..2){
val index : Int= map[i] as Int
othWords.add(selectwords.selectWordById(this@LearnActivity,index))
}
Log.d("othWords","${othWords}")
withContext(Dispatchers.Main){
when (pos) {
1 -> {
binding.mean2.text = othWords[0].tranlation
binding.mean3.text = othWords[1].tranlation
binding.mean4.text = othWords[2].tranlation
}
2 -> {
binding.mean1.text = othWords[0].tranlation
binding.mean3.text = othWords[1].tranlation
binding.mean4.text = othWords[2].tranlation
}
3 -> {
binding.mean1.text = othWords[0].tranlation
binding.mean2.text = othWords[1].tranlation
binding.mean4.text = othWords[2].tranlation
}
4 -> {
binding.mean1.text = othWords[0].tranlation
binding.mean2.text = othWords[1].tranlation
binding.mean3.text = othWords[2].tranlation
}
}
}
}
}
override fun onStart() {
super.onStart()
Log.d("LearnActivity","onStart")
}
override fun onResume() {
super.onResume()
val binding = ActivityLearnBinding.inflate(layoutInflater)
var pos: Int
trueBtn?.setOnClickListener {
if (num<10){
lifecycleScope.launch (Dispatchers.IO) {
// val word = wordList[num]
// if (word != null){
// word.selected = 1
// thread {
// Log.d("Test","$num")
// val wordDao = AppDatabase.getDatabase(this).wordDao() //在数据库中修改该单词selected为1
// wordDao.updateWord(word)
// Log.d("Test","222222222222222222")
// }
// }
withContext(Dispatchers.Main){
binding.word.text = wordList[num+1].word
pos = (1..4).random() //生成正确单词释义的位置
when (pos) { //正确单词释义按钮文本显示
1 -> {
binding.mean1.text = wordList[num+1].tranlation
trueBtn = binding.mean1
}
2 -> {
binding.mean2.text = wordList[num+1].tranlation
trueBtn = binding.mean2
}
3 -> {
binding.mean3.text = wordList[num+1].tranlation
trueBtn = binding.mean3
}
4 -> {
binding.mean4.text = wordList[num+1].tranlation
trueBtn = binding.mean4
}
}
}
val map2 = HashMap<Int, Int>()
for (i in 0..2){
var randoms = getRandoms()
while (map2.contains(randoms)||wordList[num+1].id == randoms.toLong()) {
randoms = getRandoms()
}
map2[i] = randoms
Log.d("ClickRandoms","${map2}")
}
println(map2)
val othWords2 = mutableListOf<Word>()
for (i in 0..2){
var index :Int= map2[i] as Int
Log.d("INDEX","$index")
var selectWordById = selectwords.selectWordById(this@LearnActivity, index)
othWords2.add(selectWordById)
//!!!
}
withContext(Dispatchers.Main){
when (pos) {
1 -> {
binding.mean2.text = othWords2[0].tranlation
binding.mean3.text = othWords2[1].tranlation
binding.mean4.text = othWords2[2].tranlation
}
2 -> {
binding.mean1.text = othWords2[0].tranlation
binding.mean3.text = othWords2[1].tranlation
binding.mean4.text = othWords2[2].tranlation
}
3 -> {
binding.mean1.text = othWords2[0].tranlation
binding.mean2.text = othWords2[1].tranlation
binding.mean4.text = othWords2[2].tranlation
}
4 -> {
binding.mean1.text = othWords2[0].tranlation
binding.mean2.text = othWords2[1].tranlation
binding.mean3.text = othWords2[2].tranlation
}
}
}
Log.d("othWords2","${othWords2}")
}
if (num<9) {
num++
}else{
Log.d("LOOOK","right here")
Toast.makeText(this,"你已完成学习任务",Toast.LENGTH_SHORT).show()
finish()
}
Log.d("Test","$num")
}
}
}
fun getRandoms(): Int{
val randoms = (3..13).random()
println("Randoms: "+randoms)
return randoms
}
}
这是我毕业设计的代码,自学Android写的不规范,有错误还请斧正
参考GPT和自己的思路:
根据你提供的代码,我可以看到你使用了协程来设置Button的值,这可能是导致问题的原因。lateinit var只有被正确初始化后才能被使用,而协程的运行是异步的,可能会导致在onResume()中调用trueBtn时,它还没有被正确初始化。
为了避免这个问题,建议你在onCreate()中使用普通的同步方法来初始化Button,而不是使用协程,这样可以确保在onResume()中Button已经被正确初始化。
另外,为了避免空指针异常,建议你在onResume()中也要对trueBtn是否被正确初始化进行检查,例如:
if (::trueBtn.isInitialized) {
trueBtn.setOnClickListener {
// do something
}
}
UninitializedPropertyAccessException
属性初始化的错误
参考GPT和自己的思路:
根据你提供的代码和错误信息,我认为问题可能出在onResume()函数中。在Android生命周期中,当活动从后台恢复到前台时,onResume()函数会被调用。在该函数中,你调用了trueBtn的setOnClickListener函数,但是由于意外情况(如系统内存不足),可能导致活动的onCreate()函数没有被完全执行,从而导致trueBtn变量没有被赋值。因此,当你在onResume()函数中尝试访问该变量时会抛出“lateinit property trueBtn has not been initialized”异常。
解决这个问题的方法是,你可以在调用setOnClickListener函数之前添加一个判断语句,判断是否已经赋值过,如果没有,就不调用该函数。你可以像下面这样修改你的代码:
if (::trueBtn.isInitialized) {
trueBtn.setOnClickListener {
// 点击事件的处理逻辑
}
}
这样,当trueBtn变量已经被赋值过时,才会执行setOnClickListener函数,避免出现未初始化的异常。
你为什么要用协程来初始化?
可否贴出完整代码
你写的是延迟初始化,需要有个初始化时机问题,不显式调用,是不会自动初始化的。
"协程用的出神入化"。Dispatchers.IO属于io密集型,这里有io操作没?