Android RuntimeException onCreateDialog не создал диалог для идентификатора - PullRequest
6 голосов
/ 19 ноября 2010

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

showDialog(...)
removeDialog(...)

Я немного играю с приложением, и когда на экране нет никакого диалога, я нажимаю менюи я перехожу на главный экран андроида.

Через некоторое время я снова захожу в свое приложение и иногда получаю это исключение 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);

Ответы [ 5 ]

11 голосов
/ 07 января 2011

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

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

4 голосов
/ 28 января 2011

Для версии SDK <8, если вы возвращаете ноль в onCreateDialog, вы получаете исключение java.lang.IllegalArgumentException. </p>

2 голосов
/ 28 марта 2012

После того, как я столкнулся с той же проблемой (и обнаружил, что вызов 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), выясняется, что это решение должно работать согласованно с учетом этих существующих реализаций.

0 голосов
/ 19 ноября 2010

Правильно ли вы возвращаете диалог в onCreateDialog?Если бы вы делали dialog.show () в диалоге создания, но возвращали какой-то другой диалог, вы могли бы получить такой результат.

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

0 голосов
/ 19 ноября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...