配置更改后,无法在保留的实例片段中关闭DialogFragment

时间:2015-12-21 15:13:40

标签: android android-fragments

我有一个进度对话框(使用DialogFragment实现)重新保留在保留的实例片段中。

如果没有配置更改,DialogFragment可以被解除而不会出现任何问题。

但是,如果配置发生变化,调用dismiss将不会产生任何影响。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            BackupTaskFragment backupTaskFragment = BackupTaskFragment.newInstance();
            FragmentManager fm = getFragmentManager();
            Fragment oldFragment = fm.findFragmentByTag("BACKUP_TASK_FRAGMENT");
            if (oldFragment != null) {
                fm.beginTransaction().remove(oldFragment).commit();
            }

            fm.beginTransaction().add(backupTaskFragment, "BACKUP_TASK_FRAGMENT").commit();
        }
    }
}

BackupTaskFragment.java

public class BackupTaskFragment extends Fragment {
    public static final class BackupTaskDialogFragment extends DialogFragment {
        public static BackupTaskDialogFragment newInstance() {
            return new BackupTaskDialogFragment();
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            ProgressDialog progressDialog = new ProgressDialog(this.getActivity());
            progressDialog.setMessage("Backup...");
            progressDialog.setCanceledOnTouchOutside(false);
            return progressDialog;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Retain this instance so it isn't destroyed when MainActivity and
        // MainFragment change configuration.
        setRetainInstance(true);

        backupTask = new BackupTask(this);

        backupTask.execute();

        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (isResumed() && backupTask != null) {
                    backupTaskDialogFragment = BackupTaskDialogFragment.newInstance();

                    FragmentManager fm = BackupTaskFragment.this.getFragmentManager();
                    fm.beginTransaction().add(backupTaskDialogFragment, BACKUP_TASK_DIALOG_FRAGMENT).commitAllowingStateLoss();
                }
            }
        }, 1500);
    }

    @SuppressLint("NewApi")
    public void onPause() {
        super.onPause();

        android.util.Log.i("CHEOK", "onPause");

        Activity activity = this.getActivity();

        boolean kill = false;

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
            if (activity != null && false == activity.isChangingConfigurations()) {
                // Stop the thread when home is pressed.
                kill = true;
            }
        } else {
            // I have no idea how to perform configuration checking in older API
            // Just do nothing, by letting the thread continue to run.
            //
            // http://stackoverflow.com/questions/15458540/calling-activity-ischangingconfigurations-in-fragment-for-api-level-lesser-than
        }

        if (kill) {
            if (backupTask != null) {
                backupTask.cancel(true);
                backupTask = null;
            }

            BackupTaskDialogFragment backupTaskDialogFragment = this.backupTaskDialogFragment;
            if (backupTaskDialogFragment != null) {
                android.util.Log.i("CHEOK", "onPause dismiss backupTaskDialogFragment");
                backupTaskDialogFragment.dismiss();
            }
        }
    }
    // This is also called by the AsyncTask.
    public void onPostExecute(File file) {
        if (isResumed()) {
            android.util.Log.i("CHEOK", "onPostExecute isResumed true");
        } else {
            android.util.Log.i("CHEOK", "onPostExecute isResumed false");
        }

        backupTask = null;

        BackupTaskDialogFragment backupTaskDialogFragment = this.backupTaskDialogFragment;
        if (backupTaskDialogFragment != null) {
            android.util.Log.i("CHEOK", "onPostExecute dismiss backupTaskDialogFragment");
            backupTaskDialogFragment.dismiss();
        }
    }

    public static BackupTaskFragment newInstance() {
        return new BackupTaskFragment();
    }

    private BackupTask backupTask;

    private BackupTaskDialogFragment backupTaskDialogFragment = null;

    private static final String BACKUP_TASK_DIALOG_FRAGMENT = "BACKUP_TASK_DIALOG_FRAGMENT";
}

BackupTask.java

public class BackupTask extends AsyncTask<Void, Void, File> {

    public BackupTask(BackupTaskFragment backupTaskFragment) {
        this.backupTaskFragment = backupTaskFragment;
    }

    @Override
    protected File doInBackground(Void... params) {
        android.util.Log.i("CHEOK", "BackupTask sleep for 20 seconds...");
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        android.util.Log.i("CHEOK", "BackupTask sleep for 20 seconds done!");
        return null;
    }

    @Override
    protected void onPostExecute(File file) {
        this.backupTaskFragment.onPostExecute(file);
    }

    private final BackupTaskFragment backupTaskFragment;
}

正如您所看到的,当BackupTask完成执行时,它会触发BackupTaskFragment onPostExecute,以解除BackupTaskDialogFragment

但是,在BackupTaskFragment onPostExecute之前是否有更改配置,解雇BackupTaskDialogFragment无法正常工作。

知道为什么它不起作用,我们如何解决这个问题?

完整的最小可行代码可以从https://www.dropbox.com/s/dcy856zmp18dhgk/MyApplication.zip?dl=0

下载

1 个答案:

答案 0 :(得分:1)

当配置发生变化时,this.backupTaskDialogFragment中的BackupTaskFragment不再引用当前运行的对话框片段。

而不是

BackupTaskDialogFragment backupTaskDialogFragment = this.backupTaskDialogFragment;
if (backupTaskDialogFragment != null) {

使用

public BackupTaskDialogFragment getBackupTaskDialogFragment() {
    Activity activity = getActivity();
    if (activity != null) {
        FragmentManager fm = activity.getFragmentManager();
        return (BackupTaskDialogFragment)fm.findFragmentByTag(BACKUP_TASK_DIALOG_FRAGMENT);
    }
    return null;
}
...
BackupTaskDialogFragment backupTaskDialogFragment = getBackupTaskDialogFragment();
if (backupTaskDialogFragment != null) {