Fragment在重启时错过了广播

时间:2013-01-14 07:17:20

标签: android android-intent android-orientation android-dialogfragment android-broadcast

在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 个答案:

答案 0 :(得分:0)

由于您正在使用片段,我建议您使用setRetainInstance()制作一个在配置更改中保持不变的片段。您可以从该片段注册您的广播接收器,显示或隐藏进度等。(请注意,片段不需要对用户可见。)

另一种无片段的方法是为该意图添加一个独立的BroadcastReceiver类(在您的清单中注册),并将值保存到首选项以提醒您的应用程序已收到广播。

实际上,您可以跳过独立的BroadcastReceiver,只需将值保存到AsyncTaskWithProgress的首选项中,该值指示操作的当前状态,例如: Status.LOADING,Status.LOADED,Status.CANCELLED等,并在onCreate()中检查该值。但是,我认为使用setRetainInstance()是最好的方法,因为你已经在使用片段了。