Android RuntimeException onCreateDialog не создал диалог для id

у меня есть приложение, которое вы можете показать и закрыть несколько диалогов с:

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.access00(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);

5 ответов


после возникновения этой же проблемы (и нахождения этого вызова removeDialog внутри onPause не работает надежно), я разработал обходной путь, который, кажется, функционирует (хотя, по общему признанию, это хак).

Как видно ссылка grepcode опубликована antslava метод performRestoreInstanceState, onRestoreInstanceState вызывается прямо перед restoreManagedDialogs и передается тот же экземпляр Bundle savedInstanceState.

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

таким образом, есть возможность изменить Bundle savedInstanceState это передается restoreManagedDialogs внутри onRestoreInstanceState метод.

чтобы предотвратить восстановление всех управляемых диалоговых окон, можно реализовать 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" для удаления из Bundle savedInstanceState, что впоследствии вызывает вызов restoreManagedDialogs немедленно вернуться, когда он находит, что этот ключ не может быть найден:

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

это приведет к onCreateDialog не вызываться при восстановлении Активность, эффективно "скрывающая" любые диалоги, тем самым предотвращая сценарий, когда нужно вернуть null С onCreateDialog происходит.

это не 'один размер подходит всем решение, но, учитывая мои требования вроде подходят. Просматривая код в grepcode для нескольких версий платформы (1.6, 2.1, 2.2, 2.2.2 и 4.0.3), кажется, что это решение должно работать последовательно с учетом этих существующих реализаций.


в API уровня 8,onCreateDialog(int) был устаревший в пользу onCreateDialog(int,Bundle). Если вы реализуете только последний метод и запустите приложение на устройстве с уровнем API ниже 8, вы получите описанное сообщение об ошибке.

решение заключается в реализации onCreateDialog(int)


для SDK версии


вы реализовали OnCreateDialog как представлено здесь? При первом вызове showDialog(4) будет вызван OnCreateDialog(4), и вам нужно создать диалоговое окно и вернуть его из этого метода.


вы правильно возвращаете диалог в onCreateDialog? Если вы должны были сделать диалог.show () in dialog create но return some other dialog you could maybe get a result like that.

или вы делаете какие-либо манипуляции с объектом диалога в onPrepareDialog