问题描述
我有一个应用程序,您可以显示和关闭几个对话框:
showDialog(...)
removeDialog(...)
我在应用程序中玩了一下,当屏幕上没有任何Dialog时,我按下菜单按钮,然后进入主安卓屏幕。
过了一会儿,我再次进入我的应用程序,有时,我得到这个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);
1楼
在API级别8中, onCreateDialog(int)
而 onCreateDialog(int,Bundle)
。
如果仅实现后一种方法并在API级别低于8的设备上运行应用程序,则会收到所描述的错误消息。
解决方案是实现onCreateDialog(int)
2楼
对于SDK版本<8,如果在onCreateDialog中返回null,则会出现Exception java.lang.IllegalArgumentException。
3楼
在经历了同样的问题(并发现从onPause
内部调用removeDialog
无法可靠地工作)之后,我开发了一个似乎起作用的解决方法(尽管它确实是一个黑客攻击)。
如的 ,在方法performRestoreInstanceState
, onRestoreInstanceState
在restoreManagedDialogs
之前restoreManagedDialogs
,并传递给Bundle savedInstanceState
的同一个实例。
final void performRestoreInstanceState(Bundle savedInstanceState) {
onRestoreInstanceState(savedInstanceState);
restoreManagedDialogs(savedInstanceState);
}
因此,有机会修改从onRestoreInstanceState
方法传递给restoreManagedDialogs
的Bundle savedInstanceState
。
为了防止恢复任何和所有托管对话框,可以通过以下方式实现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);
}
}
这会导致键"android:savedDialogs"
引用的Bundle
从Bundle savedInstanceState
删除,这会导致对restoreManagedDialogs
的调用在发现无法找到此键时立即返回:
private void restoreManagedDialogs(Bundle savedInstanceState) {
final Bundle b = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
if (b == null) {
return;
}
...
}
这将导致在恢复活动时不调用onCreateDialog
,有效地“隐藏”任何对话框,从而防止必须从onCreateDialog
返回null
的情况发生。
这不是一个“一刀切”的解决方案,但鉴于我的要求,它似乎符合要求。 通过查看grepcode中几个平台版本(1.6,2.1,2.2,2.2.2和4.0.3)的代码,看来这个解决方案应该在这些现有实现的情况下保持一致。
4楼
您是否实现了提供的OnCreateDialog? 当您第一次调用showDialog(4)时,将调用OnCreateDialog(4)并且您需要创建对话框并从此方法返回它。
5楼
你是否正确地在onCreateDialog
返回对话框?
如果您在对话框创建中执行dialog.show()但返回其他对话框,则可能会得到类似的结果。
或者您正在对onPrepareDialog
中的对话框对象进行任何操作