Android RuntimeException onCreateDialog 没有为 id 创建对话框

发布于 2024-10-03 12:51:22 字数 2189 浏览 2 评论 0原文

我有一个应用程序,您可以使用它来显示和关闭多个对话框:

showDialog(...)
removeDialog(...)

我稍微玩了一下该应用程序,当屏幕上没有任何对话框时,我按下菜单按钮,然后转到主 Android 屏幕。

一段时间后,我再次进入我的应用程序,有时,我会收到此 RuntimeException:

java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.access$2200(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4
    at android.app.Activity.createDialog(Activity.java:878)
    at android.app.Activity.restoreManagedDialogs(Activity.java:867)
    at android.app.Activity.performRestoreInstanceState(Activity.java:815)
    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2565)
    ... 11 more

Any idea?

非常感谢。

更新,更多信息:

当前的 onCreateDialog 实现是:

protected Dialog onCreateDialog(int id){
 Builder b = new AlertDialog.Builder(this);
 if(id == 4){
  b.setMessage(...);
  b.setItems(items, new DialogInterface.OnClickListener(){
   public void onClick(DialogInterface dialog, int which){
    Intent i = new Intent(Current.this, Another.class);
    startActivity(i);
   }
  });
  return b.create();
 }
 return null;
}

为了调用此函数,我这样做:

removeDialog(4);
showDialog(4);

I've an application that you can show and close several Dialogs with:

showDialog(...)
removeDialog(...)

I play a little bit with the application and when there is no any Dialog on the screen, I press the menu button and I go to the main android screen.

After a while, I enter again into my application and sometimes, I get this RuntimeException:

java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
    at android.app.ActivityThread.access$2200(ActivityThread.java:126)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:123)
    at android.app.ActivityThread.main(ActivityThread.java:4595)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:521)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalArgumentException: Activity#onCreateDialog did not create a dialog for id 4
    at android.app.Activity.createDialog(Activity.java:878)
    at android.app.Activity.restoreManagedDialogs(Activity.java:867)
    at android.app.Activity.performRestoreInstanceState(Activity.java:815)
    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2565)
    ... 11 more

Any idea?

Thank you very much.

UPDATE, more information:

The current onCreateDialog implementation is:

protected Dialog onCreateDialog(int id){
 Builder b = new AlertDialog.Builder(this);
 if(id == 4){
  b.setMessage(...);
  b.setItems(items, new DialogInterface.OnClickListener(){
   public void onClick(DialogInterface dialog, int which){
    Intent i = new Intent(Current.this, Another.class);
    startActivity(i);
   }
  });
  return b.create();
 }
 return null;
}

In order to call this function I do:

removeDialog(4);
showDialog(4);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

素年丶 2024-10-10 12:51:23

您是否实现了此处所示的OnCreateDialog?当您第一次调用 showDialog(4) 时,将调用 OnCreateDialog(4),您需要创建对话框并从此方法返回它。

Have you implemented OnCreateDialog as presented here? When you call showDialog(4) for the first time, OnCreateDialog(4) will be called and you need to create the dialog and return it from this method.

浅忆 2024-10-10 12:51:23

您是否在 onCreateDialog 中正确返回对话框?如果您要在对话框创建中执行dialog.show(),但返回一些其他对话框,您可能会得到这样的结果。

或者您是否在 onPrepareDialog 中对对话框对象进行任何类型的操作

Are you properly returning the dialog in onCreateDialog? If you were to do dialog.show() in dialog create but return some other dialog you could perhaps get a result like that.

Or are you doing any sort of manipulation in of the dialog object in onPrepareDialog

明天过后 2024-10-10 12:51:22

在 API 级别 8 中,onCreateDialog(int)已弃用,转而使用 onCreateDialog(int,Bundle)。如果您仅实现后一种方法并在 API 级别低于 8 的设备上运行应用程序,您会收到所描述的错误消息。

解决方案是实现onCreateDialog(int)

In API level 8, onCreateDialog(int) was deprecated in favor of onCreateDialog(int,Bundle). If you implement only the latter method and run the app on a device with an API level lower than 8, you get the described error message.

The solution is to implement onCreateDialog(int)

后来的我们 2024-10-10 12:51:22

对于SDK版本< 8、如果在 onCreateDialog 中返回 null,则会出现异常 java.lang.IllegalArgumentException。

For SDK version < 8, if you return null in onCreateDialog you get Exception java.lang.IllegalArgumentException.

等往事风中吹 2024-10-10 12:51:22

在经历了同样的问题(并发现从 onPause 中调用 removeDialog 无法可靠工作)后,我开发了一种似乎有效的解决方法(尽管这确实是一种黑客行为) 。

grepcode 链接由 antslava 发布,在方法 performRestoreInstanceState 中,onRestoreInstanceStaterestoreManagedDialogs 之前调用,并传递相同的内容Bundle savingInstanceState 的实例。

final void performRestoreInstanceState(Bundle savedInstanceState) {
    onRestoreInstanceState(savedInstanceState);
    restoreManagedDialogs(savedInstanceState);
}

因此,有机会修改从 onRestoreInstanceState 方法中传递到 restoreManagedDialogsBundle savingInstanceState

为了防止恢复任何和所有托管对话框,可以通过以下方式实现 onRestoreInstanceState

// This same variable is defined as private in the Activity class. I need
// access to it, so I redefine it here.
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (null != b) {
        savedInstanceState.remove(SAVED_DIALOGS_TAG);
    }
}

这会导致 Bundle 由键 "android:savedDialogs"< 引用/code> 从 Bundle savingInstanceState 中删除,这随后会导致对 restoreManagedDialogs 的调用在发现找不到此键时立即返回:

private void restoreManagedDialogs(Bundle savedInstanceState) {
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (b == null) {
        return;
    }
    ...
}

这将导致 onCreateDialog 在恢复活动时不会被调用,有效地“隐藏”任何对话框,从而防止发生必须从 onCreateDialog 返回 null 的情况。

这不是“一刀切”的解决方案,但考虑到我的要求,它似乎符合要求。通过检查多个平台版本(1.6、2.1、2.2、2.2.2 和 4.0.3)的 grepcode 中的代码,在考虑到这些现有实现的情况下,该解决方案似乎应该能够一致地工作。

After experiencing this same issue (and finding that calling removeDialog from within onPause doesn't work reliably), I developed a workaround that seems to function (although it's admittedly a hack).

As seen in the grepcode link posted by antslava, in method performRestoreInstanceState, onRestoreInstanceState is called right before restoreManagedDialogs and is passed the same instance of Bundle savedInstanceState.

final void performRestoreInstanceState(Bundle savedInstanceState) {
    onRestoreInstanceState(savedInstanceState);
    restoreManagedDialogs(savedInstanceState);
}

Thus, there is opportunity to modify the Bundle savedInstanceState that is passed to restoreManagedDialogs from within the onRestoreInstanceState method.

To prevent any and all managed dialogs from being restored, one could implement onRestoreInstanceState in the following way:

// This same variable is defined as private in the Activity class. I need
// access to it, so I redefine it here.
private static final String SAVED_DIALOGS_TAG = "android:savedDialogs";

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (null != b) {
        savedInstanceState.remove(SAVED_DIALOGS_TAG);
    }
}

This causes the Bundle referenced by key "android:savedDialogs" to be removed from Bundle savedInstanceState, which subsequently causes the call to restoreManagedDialogs to immediately return when it finds that this key cannot be found:

private void restoreManagedDialogs(Bundle savedInstanceState) {
    final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
    if (b == null) {
        return;
    }
    ...
}

This will cause onCreateDialog to not be called while restoring the Activity, effectively "hiding" any dialogs, thus preventing the scenario where one must return null from onCreateDialog from occurring.

This isn't a 'one size fits all' solution, but given my requirements it seems to fit the bill. By reviewing the code in grepcode for several platform versions (1.6, 2.1, 2.2, 2.2.2, and 4.0.3), it appears that this solution should work consistently given these existing implementations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文