如何在Kotlin中初始化lateinit属性,错误“kotlin.未初始化属性访问异常:lateinit属性学生尚未初始化”

ubby3x7f  于 2022-12-27  发布在  Kotlin
关注(0)|答案(2)|浏览(223)

我收到以下错误"未初始化的属性访问异常:lateinit属性学生尚未初始化"
我的代码:

package com.example.a7_simpleroomapp

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import com.example.a7_simpleroomapp.databinding.FragmentInputBinding
import kotlinx.coroutines.*

class InputFragment : Fragment() {
    private lateinit var appDb: AppDatabase

    @OptIn(DelicateCoroutinesApi::class)
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        val binding: FragmentInputBinding =
            DataBindingUtil.inflate(
                inflater,
                R.layout.fragment_input,
                container,
                false
            )
        appDb = AppDatabase.getDatabase(this.requireContext())

        binding.readButton.setOnClickListener {

            val zsid = binding.zsidText.text.toString()
            val name = binding.nameText.text.toString()
            val gender = binding.genText.text.toString()
            val school = binding.sclText.text.toString()

            if (zsid.isNotEmpty() && name.isNotEmpty() && gender.isNotEmpty() && school.isNotEmpty()) {

                val student = Student(
                    null, zsid, name, gender, school
                )
                GlobalScope.launch(Dispatchers.IO) {
                    appDb.StudentDao().insert(student)
                }

                binding.zsidText.text.clear()
                binding.nameText.text.clear()
                binding.genText.text.clear()
                binding.sclText.text.clear()
                Toast.makeText(context, "Successfully Added!", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(context, "Enter all the values to continue!", Toast.LENGTH_SHORT)
                    .show()
            }
        }

        binding.viewButton.setOnClickListener {
            val idzs = binding.zsidRead.text.toString()
            if (idzs.isNotEmpty()) {
                lateinit var student: Student
                GlobalScope.launch {
                    student = appDb.StudentDao().findByZsid(idzs)
                    Log.d("Data",student.name.toString())

                }
                    val nam = student.name.toString()
                    val gend = student.gender.toString()
                    val schl = student.school.toString()

                view?.findNavController()
                    ?.navigate(InputFragmentDirections.actionInputFragmentToDataFragment(zsid = idzs, name = nam, gender = gend, school = schl))
            } else {
                Toast.makeText(context, "Please enter any values to continue!", Toast.LENGTH_SHORT)
                    .show()
            }
        }
        return binding.root
    }
}

我不知道在哪里和如何初始化学生lateinit变量...请帮助我。我只是初学者,原谅我的错误代码

  • 我试着初始化它,但总是出错 *
lp0sw83n

lp0sw83n1#

这是因为,协程将在asyn..!中执行此操作,而您试图在Student初始化之前访问它的值。
因此按以下代码更改viewButton,

binding.viewButton.setOnClickListener {
        val idzs = binding.zsidRead.text.toString()
        if (idzs.isNotEmpty()) {
           //No need late init var. and try to use lifeCycle Aware CoroutineScope instead of GlobalScope(for good practice.) 
           //The Global Scope is not need in this Use Case. so if you want you can change "GlobalScope.launch" into "lifecycle.coroutineScope.launch"
            lifecycle.coroutineScope.launch(Dispatchers.IO) { //add lifecycle runtime dependency in gradle.
                
                var student: Student = appDb.StudentDao().findByZsid(idzs)
                Log.d("Data",student.name.toString())

                val nam = student.name.toString()
                val gend = student.gender.toString()
                val schl = student.school.toString()
             withContext(Dispatchers.Main){
            view?.findNavController()
                ?.navigate(InputFragmentDirections.actionInputFragmentToDataFragment(zsid = idzs, name = nam, gender = gend, school = schl))
            }
           }
        } else {
            Toast.makeText(context, "Please enter any values to continue!", Toast.LENGTH_SHORT)
                .show()
        }
    }

有关生命周期感知协程作用域的更多信息,请查看-https://developer.android.com/topic/libraries/architecture/coroutines#lifecyclescope

wvmv3b1j

wvmv3b1j2#

你可以通过设置一个值来初始化它--任何值,但是你需要在使用它之前完成它,否则你会得到一个错误,你的问题是你在一个协程中设置它,协程是异步的,你不能用一个lateinit var来做你想做的事情,相反,所有使用student的东西都应该在协程中。
或者你可以使用runBlocking来代替launch来启动协程,这会让剩下的代码等待协程完成后再继续,但是这仍然是异步的,所以在导航之前会有一个延迟。

相关问题