我有,你可以显示并关闭一些对话框与应用程序:
的ShowDialog(...)
removeDialog(...)
我玩的应用程序一点点,在没有任何提示信息在屏幕上,我preSS的菜单按钮,然后我去到主屏幕的android
过了一会儿,我又进入我的应用程序,有时,我得到这个RuntimeException的:
java.lang.IllegalArgumentException:如果活动#onCreateDialog没有为ID 4创建一个对话框
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2596)
在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621)
在android.app.ActivityThread.access $ 2200(ActivityThread.java:126)
在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1932)
在android.os.Handler.dispatchMessage(Handler.java:99)
在android.os.Looper.loop(Looper.java:123)
在android.app.ActivityThread.main(ActivityThread.java:4595)
在java.lang.reflect.Method.invokeNative(本机方法)
在java.lang.reflect.Method.invoke(Method.java:521)
在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:860)
在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
在dalvik.system.NativeStart.main(本机方法)
java.lang.IllegalArgumentException异常:产生的原因活动#onCreateDialog没有为ID 4创建一个对话框
在android.app.Activity.createDialog(Activity.java:878)
在android.app.Activity.restoreManagedDialogs(Activity.java:867)
在android.app.Activity.performRestoreInstanceState(Activity.java:815)
在android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1096)
在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2565)
... 11更多
你知道吗?
非常感谢你。
更新,更多的信息:
目前onCreateDialog实现是:
保护对话框onCreateDialog(INT ID){
生成器B =新AlertDialog.Builder(本);
如果(ID == 4){
b.setMessage(...);
b.setItems(项目,新DialogInterface.OnClickListener(){
公共无效的onClick(DialogInterface对话,诠释它){
意图I =新的意图(Current.this,Another.class);
startActivity(ⅰ);
}
});
返回b.create();
}
返回null;
}
为了调用这个函数我做的:
removeDialog(4);
的ShowDialog(4);
解决方案
在遇到同样的问题(并发现主叫 removeDialog
从内部的onPause
不正常),我开发了一个解决方法,似乎功能(虽然这是无可否认的黑客攻击)。
如图中的grep code发表antslava 环节,方法 performRestoreInstanceState
, onRestoreInstanceState
被称为前右 restoreManagedDialogs
,并通过了捆绑savedInstanceState
。
最终无效performRestoreInstanceState(包savedInstanceState){
onRestoreInstanceState(savedInstanceState);
restoreManagedDialogs(savedInstanceState);
}
因此,有机会修改捆绑savedInstanceState
是内传递到 restoreManagedDialogs
从 onRestoreInstanceState
方法。
要prevent任何和进行恢复,人们可以实施 onRestoreInstanceState
通过以下方式管理所有的对话框:
//这同一个变量被定义为私有的Activity类。我需要
//访问它,所以我重新定义在这里。
私有静态最后弦乐SAVED_DIALOGS_TAG =机器人:savedDialogs;
@覆盖
保护无效onRestoreInstanceState(包savedInstanceState){
super.onRestoreInstanceState(savedInstanceState);
最后叠B = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
如果(空!= b)的{
savedInstanceState.remove(SAVED_DIALOGS_TAG);
}
}
这使得捆绑
通过按键引用的机器人:savedDialogs
从捆绑savedInstanceState ,随后将导致调用 restoreManagedDialogs
时,发现该键无法找到立即返回:
私人无效restoreManagedDialogs(包savedInstanceState){
最后叠B = savedInstanceState.getBundle(SAVED_DIALOGS_TAG);
如果(二== NULL){
返回;
}
...
}
这将导致 onCreateDialog
来不能称之为同时恢复活动,有效地隐藏任何对话,因此preventing场景,其中一个必须返回空
从 onCreateDialog
的发生。
这是不是一个一刀切的解决方案,但由于我的要求似乎符合这个要求。通过查看code中的grep code几个平台的版本(1.6,2.1,2.2,2.2.2,4.0.3和),看来这个解决方案应该始终考虑到这些已有的实现。
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);
解决方案
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.