由于打开的对话框,应用程序在初始化期间崩溃

App crashes during initialization because of opened dialog

这个崩溃已经在我的开发者控制台中出现很长时间了,我一直无法以任何方式重现它。

我有一个以 MainActivity 开头的应用程序。在onCreate中,一些数据是从后端异步下载的。当按下此 activity 中的按钮时,将打开一个对话框,显示从服务器下载的一些数据。

这是崩溃:

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.******.******/com.******.******.MainActivity}: com.******.******.users.UserData$DataNotFoundException: Requested element not found
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
       at android.app.ActivityThread.-wrap11(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6942)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Caused by com.******.******.users.UserData$DataNotFoundException: Requested element not found
       at com.******.******.users.UserData.getData(UserData.java:478)
       at com.******.******.UserDialog.onCreateDialog(UserDialog.java:87)
       at androidx.fragment.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:380)
       at androidx.fragment.app.Fragment.performGetLayoutInflater(Fragment.java:1412)
       at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
       at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
       at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
       at androidx.fragment.app.FragmentManagerImpl.dispatchStateChange(FragmentManagerImpl.java:2659)
       at androidx.fragment.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManagerImpl.java:2613)
       at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:246)
       at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:542)
       at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
       at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1341)
       at android.app.Activity.performStart(Activity.java:7200)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2920)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3032)
       at android.app.ActivityThread.-wrap11(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6942)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

令我感到困惑的是,由于对话框膨胀时发生崩溃,导致 performLaunchActivity 发生崩溃。但是,对话框不是在 activity 的 onCreate 中创建的,而是仅在用户按下按钮后才创建的。但是按钮没有被点击(我在点击监听器中添加了一个日志,但它从未被调用)。

我在 GitHub 问题跟踪器中看到过类似模式的崩溃,但没有回复,所以这似乎是一种常见模式,但很难调试。

问题是在什么情况下可以从 performLaunchActivity 实例化对话框,即使在 onCreate() 方法中没有引用对话框。我猜这与活动的生命周期有关,但我一直无法破解。

@ig343

你的问题好像是因为

Caused by com.******.******.users.UserData$DataNotFoundException: Requested element not found
   at com.******.******.users.UserData.getData(UserData.java:478)

选项 1: 使用异常处理程序 {try catch to handle DataNotFoundException} for line (UserData.java:478) 并记录错误。

选项 2: 尝试将所有 Requested 元素值都设为 null。

玩得开心....

您的崩溃可能发生在屏幕旋转时,或者应用程序在后台进程死亡后恢复时。在这种情况下,DialogFragment 是在没有用户交互的情况下创建的。您是否检查并推理了这些情况?

您可能希望在按照 documentation 打开对话框时将数据作为参数传递。这样,系统将重新创建数据完整的对话框。

如果 Android 需要在显示对话框时重新创建一个 activity,它将在重新创建 activity 时重新创建对话框。例如,您的 activity 在后台运行时可能会被杀死,以便为前台应用程序释放内存。

在这种情况下,如果您的对话框使用 activity 被杀死之前存在于内存中的数据,那么您的对话框可能 运行 出现问题,但这些数据不会通过对话框再次实例化。

由于这个原因,对话框有参数,这些参数会被保留并在重新创建对话框时传递给对话框。 使用 setArguments(Bundle args) 将数据传递给对话框。

根据你的堆栈跟踪,我猜你有函数或使用了某种全局变量,当你异步获取数据时它会发生变化,然后它崩溃,因为你的 dialog 还没有膨胀。

我最好的猜测是您使用了 DialogFragment 并且它的生命周期与常规片段有点不同,它正在尝试准备将要在布局中的数据。

我只是在这里猜测,因为你的问题不够清楚但是为了调试和修复这个问题我建议你改变你的 getData 方法并在其中放入一个常量数据以查看崩溃是否仍然存在会发生,如果崩溃停止是因为你使用的变量并且应该处理你的片段和对话框生命周期来修复崩溃,如果崩溃仍然会发生改变常规片段并且只是 post 发生了什么所以我可以知道什么正在发生。

总的来说,当您使用某些变量或使用尚未生成的数据填充某些视图时会发生这种情况,如果您尝试更改已在其中使用的视图或变量,也可能是由该异步方法引起的主线程。

让我 posted 并希望这对您有所帮助。

这就是为什么大多数应用在异步获取数据时都会出现加载屏幕的原因。 可能是您的代码没有任何问题,但用户能够以某种方式在获取数据之前点击按钮。 您可以尝试在性能较差 phone 的模拟器上部署该应用程序。 检查发生崩溃的 phone 的型号