6

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

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

任何的想法?

非常感谢你。

更新,更多信息:

当前的 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);
4

5 回答 5

11

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

解决方案是实施onCreateDialog(int)

于 2011-01-06T21:33:18.260 回答
4

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

于 2011-01-28T13:01:37.593 回答
2

在遇到同样的问题(并发现removeDialog从内部调用onPause不能可靠地工作)之后,我开发了一个似乎可以正常工作的解决方法(尽管它是公认的 hack)。

正如antslava 发布的 grepcode 链接中所见,在 methodperformRestoreInstanceState中,onRestoreInstanceState在之前被调用restoreManagedDialogs并传递了相同的Bundle savedInstanceState.

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

因此,有机会修改从方法Bundle savedInstanceState中传递给的。restoreManagedDialogsonRestoreInstanceState

为了防止任何和所有托管对话框被恢复,可以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);
    }
}

这会导致从Bundlekey"android:savedDialogs"中删除所引用的Bundle savedInstanceState内容,从而导致调用 torestoreManagedDialogs在发现无法找到此 key 时立即返回:

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

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

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

于 2012-03-28T16:31:27.823 回答
0

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

于 2010-11-19T13:45:13.673 回答
0

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

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

于 2010-11-19T15:59:52.627 回答