首页 > 解决方案 > Android 崩溃 - kotlin.UninitializedPropertyAccessException MainActivity.getAdapterGallery

问题描述

在 google play 控制台中,我看到许多只有最新设备和 Android 11 的用户发生了这个崩溃:

kotlin.UninitializedPropertyAccessException
de.xxx.blabla.MainActivity.getAdapterGallery

我什至没有任何被调用的类/方法getAdapterGallery

大头钉轨迹是:

java.lang.RuntimeException: 
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4864)
  at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4901)
  at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:52)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2307)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8512)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1139)
Caused by: java.lang.RuntimeException: 
  at android.app.ActivityThread.deliverResults (ActivityThread.java:5506)
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4851)
  at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4901)
  at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:52)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2307)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8512)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1139)
Caused by: kotlin.UninitializedPropertyAccessException: 
  at de.xxx.blabla.MainActivity.getAdapterGallery (MainActivity.java:7)
  at de.xxx.blabla.MainActivity.onActivityResult (MainActivity.java)
  at android.app.Activity.dispatchActivityResult (Activity.java:8541)
  at android.app.ActivityThread.deliverResults (ActivityThread.java:5499)
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:4851)
  at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:4901)
  at android.app.servertransaction.ResumeActivityItem.execute (ResumeActivityItem.java:52)
  at android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:176)
  at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2307)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:246)
  at android.app.ActivityThread.main (ActivityThread.java:8512)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1139)


EDIT:

这就是我在 onActivityResult 中的内容:

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, intent)

    if(requestCode == 777 && resultCode == RESULT_OK && data != null) {

        if(data.hasExtra("commentCountChanged")) {
            val json = JSONObject(data.getStringExtra("commentCountChanged")!!)

            val memeID = json.getLong("memeID")
            val commentCount = json.getInt("commentCount")

            for (i in 0 until adapterMemes.memes.size) {
                if (adapterMemes.memes[i].id == memeID) {

                    adapterMemes.memes[i].commentcount = commentCount

                    val viewHolder = recyclerViewMemes.findViewHolderForAdapterPosition(i) as RecyclerView.ViewHolder

                    if (commentCount == 0) {
                        viewHolder.itemView.memeCommentsCount.text = "\u25CF"
                        viewHolder.itemView.memeCommentsCount.setTextSize(
                            TypedValue.COMPLEX_UNIT_SP,
                            8f
                        )
                    } else {
                        viewHolder.itemView.memeCommentsCount.text =
                            commentCount.toString()
                        viewHolder.itemView.memeCommentsCount.setTextSize(
                            TypedValue.COMPLEX_UNIT_SP,
                            16f
                        )
                    }

                    break
                }
            }
        }

        if(data.hasExtra("list")) {
            val updatedMemes = data.getParcelableArrayListExtra<Memes>("list") as ArrayList<Memes>

            val finalMemes: MutableList<Memes> = mutableListOf()
            for(i in 0 until updatedMemes.size){
                if(updatedMemes[i].title != "show_ad_break"){
                    finalMemes.add(updatedMemes[i])
                }
            }

            adapterGallery.memes = finalMemes
            adapterGallery.notifyDataSetChanged()
        }
    }
}

标签: android

解决方案


我什至没有任何名为 getAdapterGallery 的类/方法

是的你是。您有一个名为 的 Kotlin 属性adapterGallery,如您在代码中所见:

            adapterGallery.memes = finalMemes
            adapterGallery.notifyDataSetChanged()

就 JVM 实现而言,Kotlin 属性由一个 Java 字段加上一个 getter 和 setter 对组成。一个名为的属性的 getteradapterGallerygetAdapterGallery().

因此,根据错误消息,您已定义adapterGallery为 a ,并且在您到达该引用lateinit var中的代码时尚未填充它。例如,在以下情况下可能会发生此错误:onActivityResult()adapterGallery

  • 用户导航到任何向您返回结果的活动
  • 用户离开您的应用程序(例如,系统 HOME 导航、切换到另一个任务、响应通知、响应来电)
  • 当您的应用程序在后台运行时,Android 会终止您的进程以释放系统 RAM,因为您的用户拥有一部 RAM 有限的低端手机,但也有一堆繁忙的应用程序
  • 用户在离开应用后的 30 分钟内返回到您的应用,因此 Android 将用户返回到他们上次使用的活动,以试图保持您的应用一直存在的错觉,尽管它的过程已经终止
  • 用户在该活动中执行某些操作以返回已调用的活动,该活动startActivityForResult()在此过程中不存在,并且onActivityResult()在您有机会设置 UI 之前Android 调用

在现代 Android 应用程序架构中,onActivityResult()不会操作任何小部件或与这些小部件紧密耦合的对象(例如 a RecyclerView.Adapter)。相反,onActivityResult()会更新一些状态持有者(例如 a ViewModel),然后使用反应式 API(例如 )发出一些新结果(例如,视图状态LiveData)。然后,只要您的代码仅在您的小部件准备好使用数据后才观察反应式 API,您就可以避免这种崩溃。

另一种方法是首先尝试消除onActivityResult()。在现代 Android 应用程序开发中,我们尝试使用很少的活动,将屏幕实现为片段(或可组合)。您的代码onActivityResult()表明您正在响应您的其他活动的某些结果。也许您应该用一个活动替换这两个活动,以其他方式更新屏幕(片段、可组合、切换视图可见性等)。

许多有关 Android 应用程序开发的书籍和课程都介绍了这些更现代的技术。专注于过去三年内撰写或更新的内容。

无论您是否更新您的应用程序以使用现代推荐做法,您都需要确保不要尝试操作lateinit var尚未初始化的 a。


推荐阅读