Фрагмент пропускает трансляции при перезапуске

На Android я реализовал класс AsyncTaskWithProgress, который будет отображать диалоговое окно прогресса, пока выполняется фоновая работа задачи:

public abstract class AsyncTaskWithProgress<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {

private final FragmentActivity activity;
private final String action;
private final String title;
private final String message;
private final int icon;

public AsyncTaskWithProgress(FragmentActivity activity, String title, String message, int icon) {
    this.activity = activity;
    this.title = title;
    this.message = message;
    this.icon = icon;
    this.action = "" + hashCode();
}

@Override
protected final void onPreExecute() {
    DialogFragment fragment = ProgressDialogFragment.getInstance(action, title, message, icon);
    fragment.show(activity.getSupportFragmentManager(), "dialog");
    actualOnPreExecute();
}

protected void actualOnPreExecute() {
}

protected final void onPostExecute(Result result) {
    actualOnPostExecute(result);
    context.sendBroadcast(new Intent(action));
}

protected void actualOnPostExecute(Result result) {
}

}

Мой ProgressDialogFagment регистрирует BroadcastReceiver и отменяет диалог, как только трансляция получена - отрывок:

    public static Dialog getDialog(Activity activity, final String action, String title, String message, int icon,
        SerializableOnClickListener cancelListener) {
    final ProgressDialog dialog = new ProgressDialog(activity);
    dialog.setIndeterminate(true);
    dialog.setOwnerActivity(activity);
    dialog.setTitle(title);
    dialog.setMessage(message);
    if (cancelListener != null) {
        dialog.setButton(ProgressDialog.BUTTON_POSITIVE, "Cancel", cancelListener);
    }
    if (icon != MathUtils.NOT_AN_INT) {
        dialog.setIcon(icon);
    }

    BroadcastReceiver dismissReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            dialog.dismiss();
            context.unregisterReceiver(this);
            Log.d(getClass().getSimpleName(), "Dialog dismissed");
        }
    };
    context.registerReceiver(dismissReceiver, new IntentFilter(action));

    return dialog;
}

Это работает в целом. Тем не менее, время от времени диалог не отменяется, и кажется, что происходит изменение ориентации.

Я предполагаю, что во время изменения ориентации фрагмент диалога уничтожается и воссоздается. Если AsyncTask отправляет сообщение «Готово!» трансляция после того, как фрагмент был уничтожен и до того, как он был восстановлен, фрагмент пропускает трансляцию и, следовательно, никогда не удаляется.

Верна ли моя догадка? Как это реализовать более надежным способом?




Ответы (1)


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

Другой подход, который работает без фрагментов, состоит в том, чтобы добавить автономный класс BroadcastReceiver (зарегистрированный в манифесте) для этого намерения и сохранить значение в настройках, чтобы предупредить ваше приложение о получении широковещательной рассылки.

Фактически, вы можете пропустить автономный BroadcastReceiver и просто сохранить значение в настройках из вашего AsyncTaskWithProgress, которое указывает текущее состояние операции, например. Status.LOADING, Status.LOADED, Status.CANCELED и т. д. и проверьте это значение в onCreate(). Однако я думаю, что использование setRetainInstance() — лучший подход, поскольку вы уже используете фрагменты.

person Lorne Laliberte    schedule 23.01.2013
comment
Я попробовал второе из ваших предложений - похоже, сработало, но setRetainInstance() намного чище в использовании (и я не знал об этом). Я соответствующим образом изменил свой код, и до сих пор больше не было неотклоненных диалогов - я буду следить за этим и приму ваш ответ, как только буду уверен, что он действительно решил мою проблему. Вы ответили точно в мой день рождения, кстати - удачное время :-) - person csoltenborn; 29.01.2013
comment
@csoltenborn, с днем ​​рождения! :) - person Lorne Laliberte; 30.01.2013