Android的RuntimeException的onCreateDialog没有创建ID的对话RuntimeException、Android、ID、onCreateDialog

2023-09-05 03:52:02 作者:最爱旺仔i

我有,你可以显示并关闭一些对话框与应用程序:

 的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;
}
 
Android程序 java.lang.RuntimeException Unable to instantiate activity ComponentInfo.....

为了调用这个函数我做的:

  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.