防止 ProgressDialog 在旋转时被关闭,但仍然允许从 AsyncTask 中关闭
Prevent a ProgressDialog from being dismissed on rotation but still allow dismissal from AsyncTask
抱歉标题太长。我的问题如下:我使用 DialogFragment 来防止轮换时关闭 AlertDialogs(类似于此处的答案:Prevent dialog dismissal on screen rotation in Android)。
现在,我 运行 在后台执行一些可能需要几秒钟的任务。我想显示一个进度对话框来告诉用户发生了什么。任务完成后,应从 AsyncTask 中的 finished-method 中关闭 ProgressDialog。
像上面的 link 一样,我使用 DialogFragment 创建一个对话框。该对话框在旋转时保留(这很好)。然而,一旦我的任务完成并且屏幕被旋转,我就无法关闭该对话框。
以下是我尝试过的策略(如果屏幕没有旋转,这两种方法都有效):
- 正在调用 DialogFragment 的 "dismiss()"。屏幕旋转后,这会导致崩溃
java.lang.NullPointerException:尝试在空 object 引用上调用虚方法 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()'
android.app.DialogFragment.dismissInternal(DialogFragment.java:296)
android.app.DialogFragment.dismiss(DialogFragment.java:267)
- 调用某些调用 "getDialog().dismiss()" 的内部方法:getDialog() returns 尽管显示了对话框,但始终为空(旋转后)。
有人能指引我正确的方向吗?
编辑:这是一些代码
在 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;
}
}
谢谢并致以最诚挚的问候,
卡尔
谢谢 Selvin,您的代码和评论为我指明了正确的方向。
问题是我必须在关闭时重新获取片段。此外,由于关闭对话框时 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();
再次感谢您的帮助。
抱歉标题太长。我的问题如下:我使用 DialogFragment 来防止轮换时关闭 AlertDialogs(类似于此处的答案:Prevent dialog dismissal on screen rotation in Android)。
现在,我 运行 在后台执行一些可能需要几秒钟的任务。我想显示一个进度对话框来告诉用户发生了什么。任务完成后,应从 AsyncTask 中的 finished-method 中关闭 ProgressDialog。
像上面的 link 一样,我使用 DialogFragment 创建一个对话框。该对话框在旋转时保留(这很好)。然而,一旦我的任务完成并且屏幕被旋转,我就无法关闭该对话框。
以下是我尝试过的策略(如果屏幕没有旋转,这两种方法都有效):
- 正在调用 DialogFragment 的 "dismiss()"。屏幕旋转后,这会导致崩溃 java.lang.NullPointerException:尝试在空 object 引用上调用虚方法 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' android.app.DialogFragment.dismissInternal(DialogFragment.java:296) android.app.DialogFragment.dismiss(DialogFragment.java:267)
- 调用某些调用 "getDialog().dismiss()" 的内部方法:getDialog() returns 尽管显示了对话框,但始终为空(旋转后)。
有人能指引我正确的方向吗?
编辑:这是一些代码
在 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;
}
}
谢谢并致以最诚挚的问候, 卡尔
谢谢 Selvin,您的代码和评论为我指明了正确的方向。
问题是我必须在关闭时重新获取片段。此外,由于关闭对话框时 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();
再次感谢您的帮助。