【问题标题】:Prevent a ProgressDialog from being dismissed on rotation but still allow dismissal from AsyncTask防止 ProgressDialog 在轮换时被解散,但仍允许从 AsyncTask 解散
【发布时间】:2017-02-09 11:04:45
【问题描述】:

为长标题道歉。我的问题如下:我使用 DialogFragment 来防止 AlertDialogs 在旋转时被解除(类似于这里的答案:Prevent dialog dismissal on screen rotation in Android)。

现在,我在后台运行一些可能需要几秒钟的任务。我想显示一个进度对话框来告诉用户发生了什么。任务完成后,ProgressDialog 应该从 AsyncTask 中的完成方法中关闭。

与上面的链接一样,我使用 DialogFragment 创建一个 Dialog。对话框在旋转时保留(这很好)。然而,一旦我的任务完成并且屏幕被旋转,我就无法关闭对话框。

以下是我尝试过的策略(如果不旋转屏幕,这两种方法都有效):

  • 调用 DialogFragment 的“dismiss()”。屏幕旋转后,这会导致崩溃 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()” android.app.DialogFragment.dismissInternal(DialogFragment.java:296) android.app.DialogFragment.dismiss(DialogFragment.java:267)
  • 调用一些调用“getDialog().dismiss()”的内部方法:getDialog() 始终返回 null(旋转后),尽管显示了对话框。

有人能引导我走向正确的方向吗?

编辑:这是一些代码

在 Activity 内部,我只是创建了一个 TaskFragment 来做一些后台工作:

public class MainActivity extends AppCompatActivity {

    private TaskFragment ft;

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

        ft = (TaskFragment) getFragmentManager().findFragmentByTag("task");

        if(ft == null) {
            // create new
            ft = TaskFragment.newInstance();

            FragmentTransaction transaction = getFragmentManager().beginTransaction();
            transaction.add(ft, "task");
            transaction.commit();
        }
    }
}

在 TaskFragment 中,我运行了一个 AsyncTask。在 onPreExecute 我显示一个 ProgressDialog,在 onPostExecute 我关闭它:

public class TaskFragment extends Fragment {

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

    public TaskFragment() {}

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

        // Run a background task and show a dialog
        new AsyncTask<Void, Void, Void>() {
            MyDialogFragment ft;

            @Override
            protected void onPreExecute() {
                // show progress dialog
                ft = MyDialogFragment.newInstance();
                ft.show(getActivity().getFragmentManager(), "dialog");
            }

            @Override
            protected Void doInBackground(Void...params) {
                try {
                    // Do some work...
                    Thread.sleep(5000);
                } catch (InterruptedException ignored) {}

                return null;
            }

            @Override
            protected void onPostExecute(Void p) {
                // remove progress dialog
                ft.dismiss();
            }
        }.execute();
    }
}

DialogFragment 如下:

public class MyDialogFragment extends DialogFragment {
    public static MyDialogFragment newInstance() {
        MyDialogFragment fragment = new MyDialogFragment();
        return fragment;
    }

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

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        ProgressDialog dialog = new ProgressDialog(getActivity());

        dialog.setIndeterminate(true);

        dialog.setTitle("Hello World");

        return dialog;
    }
}

感谢和最好的问候, 卡尔

【问题讨论】:

  • 最小代码在哪里? ...
  • 刚刚添加了最少的代码。感谢您的代码,我认为它为我指明了正确的方向(我认为 DialogFragments 被保留并且在旋转后不会重新创建)。会检查。谢谢(很抱歉没有首先添加最小的代码示例。
  • 正如您在我的链接中看到的那样,DialogFragment 应该包含“工作”片段
  • 我的 JobFragment 要大得多,我只需要进度对话框来提供一些初始化代码比预期花费的时间更长的反馈。事实上,我会在 1 秒后检查初始化是否完成,然后才显示对话框。

标签: android dialog progressdialog android-dialogfragment dialogfragment


【解决方案1】:

感谢 Selvin,您的代码和评论为我指明了正确的方向。

问题是我必须在关闭 Fragment 时重新获取它。此外,由于在关闭对话框时 Activity 可能不处于活动状态,因此我需要在关闭它时允许状态丢失以避免 NullPointerException。因此,我将 AsyncTask 更新为以下内容,它工作正常。

        // Run a background task and show a dialog
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected void onPreExecute() {
            // show progress dialog
            MyDialogFragment ft = MyDialogFragment.newInstance();
            ft.show(getActivity().getFragmentManager(), "dialog");
        }

        @Override
        protected Void doInBackground(Void...params) {
            try {
                // Do some work...
                Thread.sleep(5000);
            } catch (InterruptedException ignored) {}

            return null;
        }

        @Override
        protected void onPostExecute(Void p) {
            MyDialogFragment ft = 
                (MyDialogFragment) getFragmentManager()
                .findFragmentByTag("dialog");

            // remove progress dialog
            ft.dismissAllowingStateloss();
        }
    }.execute();

再次感谢您的帮助。

【讨论】:

    猜你喜欢
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多