在Activity中访问data类对象触发lateinit未初始化异常如何解决?
异常根因
UninitializedPropertyAccessException是因为lateinit修饰的content变量在首次访问content.isSelected前没有完成赋值,lateinit要求变量必须在第一次被访问前初始化,否则就会抛出该异常。
异常解决方法
你需要在访问content的属性前完成该变量的初始化,对于Activity场景来说,Content实例通常由上一级页面通过Intent参数传入,具体实现步骤如下:
- 先让
Content实现Parcelable接口支持跨页面传输:
import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize data class Content( val id: Int, val text: String, val isSelected: Boolean?, val url: String? ) : Parcelable
- 在上一级启动
PictureActivity的位置传入Content实例:
val intent = Intent(context, PictureActivity::class.java).apply { putExtra("EXTRA_CONTENT", 你的Content实例对象) } context.startActivity(intent)
- 在
PictureActivity的onCreate中先获取参数赋值给content,再访问其属性:
class PictureActivity : BaseActivity() { private lateinit var binding: PictureActivityBinding private lateinit var content: Content override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = PictureActivityBinding.inflate(layoutInflater) setContentView(binding.root) // 优先完成content初始化 content = intent.getParcelableExtra<Content>("EXTRA_CONTENT") ?: run { // 无法获取Content时的异常处理,例如直接关闭页面 finish() return } // 初始化完成后再访问属性,替换!!为空安全判断避免空指针 if(content.isSelected == true){ binding.button1.setOnClickListener{ content.url?.let { url -> startContentDownload(url) } } } } private fun startContentDownload(url: String) { //download image } }
访问data类对象的其他可行方案
如果你无法保证lateinit变量的初始化时机,可以选择以下更安全的方案声明Content对象:
- 方案1:声明为可空类型,初始值为null
后续访问全部使用空安全语法:// 声明时直接赋值为null private var content: Content? = nullcontent?.isSelected == true、content?.url?.let { },不会触发未初始化异常,只需要处理空场景即可。 - 方案2:使用
lazy延迟初始化
适合Content实例可以在当前页面内部生成、不需要依赖外部传入的场景:
该方案自动处理初始化时机,线程安全,无需手动管理初始化状态。private val content: Content by lazy { // 此处写初始化逻辑,只会在content第一次被访问时执行一次 Content(id = 1, text = "默认内容", isSelected = false, url = "https://xxx.com/xxx.jpg") }
注意:
lateinit只适合你100%确定变量会在首次访问前完成赋值的场景,如果存在初始化失败、参数丢失的可能性,优先使用可空类型更稳妥,同时不要随意使用!!强制拆箱可空类型,避免额外引入空指针崩溃。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

