抱歉我的英文
这不是问题。我发布它是因为这可能对某人有帮助。我的解决方案基于几个月前放置here的解决方案,但后来作者将其删除了。但是他的解决方案中存在一些错误,我试图修复它们。
即使您在应用中执行了长时间执行的任务时打开了另一个应用,然后在另一个应用中更改了屏幕方向,并在完成任务后返回到您的应用,我的解决方案也能正常工作。
如果您在我的解决方案中发现错误,请告知我们。
看看:
public interface AbleToStartTask {
void startTask(int requestCode, TaskNotBeInterruptedDuringConfigurationChange task);
void startTask(int requestCode, TaskNotBeInterruptedDuringConfigurationChange task, Integer titleId);
}
public interface TaskResultReceiver {
void onTaskResult(int requestCode, int resultCode, Serializable result);
}
public abstract class TaskNotBeInterruptedDuringConfigurationChange extends AsyncTask<Void, Void, Serializable> {
private TaskFragment fragment;
final void setFragment(TaskFragment fragment) {
this.fragment = fragment;
}
@Override
protected final void onPostExecute(Serializable result) {
if (fragment != null) {
fragment.onTaskFinished(result);
}
}
}
public class TaskFragment extends android.support.v4.app.DialogFragment {
public static final Integer NO_TITLE_ID = null;
private boolean isNeedToReturnResult = false;
private boolean isResultReturned = false;
private TaskNotBeInterruptedDuringConfigurationChange task;
private int resultCode = Activity.RESULT_CANCELED;
private Serializable result = null;
private Integer titleId;
public void setTask(TaskNotBeInterruptedDuringConfigurationChange task) {
task.setFragment(this);
this.task = task;
}
public void setTitle(Integer titleId) {
this.titleId = titleId;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
if (savedInstanceState == null && task != null) {
task.execute();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
initDialog();
return inflater.inflate(R.layout.fragment_task, container);
}
private void initDialog() {
if (titleId == NO_TITLE_ID) {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);
} else {
getDialog().setTitle(titleId);
}
getDialog().setCanceledOnTouchOutside(false);
}
@Override
public void onDestroyView() {
if ((getDialog() != null) && getRetainInstance()) {
getDialog().setDismissMessage(null);
}
super.onDestroyView();
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (task != null) {
task.cancel(false);
}
tryReturnResult();
}
private void tryReturnResult() {
task = null;
if (isResultReturned) {
return;
}
if (getTargetFragment() != null) {
returnResult();
}
}
private void returnResult() {
isResultReturned = true;
FragmentAbleToStartTask ableToStartTask = (FragmentAbleToStartTask) getTargetFragment();
if (ableToStartTask.isAbleToReceiveResult()) {
ableToStartTask.onResult(FragmentAbleToStartTask.TASK_FRAGMENT_TARGET, resultCode, result);
isNeedToReturnResult = false;
finishFragment();
} else {
isNeedToReturnResult = true;
}
}
private void finishFragment() {
if (isResumed()) {
dismiss();
}
}
@Override
public void onResume() {
super.onResume();
if (task == null) {
dismiss();
}
}
public void onTaskFinished(Serializable result) {
setResult(Activity.RESULT_OK, result);
tryReturnResult();
}
private void setResult(int resultCode, Serializable result) {
this.resultCode = resultCode;
this.result = result;
}
public void getResultIfItReturnedDuringPause() {
if (isNeedToReturnResult) {
returnResult();
}
}
}
public abstract class FragmentAbleToStartTask extends android.support.v4.app.Fragment
implements AbleToStartTask, TaskResultReceiver {
public static final int TASK_FRAGMENT_TARGET = 123;
protected static final String TAG_TASK_FRAGMENT = FragmentAbleToStartTask.class.getName() + "TAG_TASK_FRAGMENT";
private static final String KEY_TASK_REQUEST_CODE = "KEY_TASK_REQUEST_CODE";
private FragmentManager fragmentManager;
private int taskRequestCode;
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_TASK_REQUEST_CODE, taskRequestCode);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
restoreState(savedInstanceState);
}
fragmentManager = getFragmentManager();
TaskFragment taskFragment = getTaskFragment();
if (taskFragment != null) {
taskFragment.setTargetFragment(this, TASK_FRAGMENT_TARGET);
}
}
private void restoreState(Bundle savedInstanceState) {
taskRequestCode = savedInstanceState.getInt(KEY_TASK_REQUEST_CODE);
}
private TaskFragment getTaskFragment() {
return (TaskFragment) fragmentManager.findFragmentByTag(TAG_TASK_FRAGMENT);
}
public void startTask(int requestCode, TaskNotBeInterruptedDuringConfigurationChange task) {
startTask(requestCode, task, TaskFragment.NO_TITLE_ID);
}
public void startTask(int requestCode, TaskNotBeInterruptedDuringConfigurationChange task, Integer title) {
this.taskRequestCode = requestCode;
TaskFragment taskFragment = new TaskFragment();
taskFragment.setTitle(title);
taskFragment.setTask(task);
taskFragment.setTargetFragment(this, TASK_FRAGMENT_TARGET);
startFragment(taskFragment);
}
private void startFragment(TaskFragment taskFragment) {
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment previousTaskFragment = fragmentManager.findFragmentByTag(TAG_TASK_FRAGMENT);
if (previousTaskFragment != null) {
transaction.remove(previousTaskFragment);
}
transaction.add(taskFragment, TAG_TASK_FRAGMENT);
transaction.commit();
}
public final void onResult(int requestCode, int resultCode, Serializable result) {
if ((requestCode == TASK_FRAGMENT_TARGET)) {
onTaskResult(this.taskRequestCode, resultCode, result);
}
}
public abstract void onTaskResult(int requestCode, int resultCode, Serializable result);
public boolean isAbleToReceiveResult() {
return isResumed();
}
@Override
public void onResume() {
super.onResume();
TaskFragment taskFragment = getTaskFragment();
if (taskFragment != null) {
taskFragment.getResultIfItReturnedDuringPause();
}
}
}
因此FragmentAbleToStartTask
的每个继承者都必须实现onTaskResult(requestCode, resultCode, result)
。在onTaskResult()
- requestCode
中传递给startTask(requestCode, ...)
的值。请注意,此片段只能同时执行一项任务。
TaskNotBeInterruptedDuringConfigurationChange
子类的示例:
public class SomeLongTask extends TaskNotBeInterruptedDuringConfigurationChange {
private final Context context;
private final Worker worker;
public SomeLongTask (Worker worker, Context context) {
this.worker= worker;
this.context = context;
}
@Override
protected Serializable doInBackground(Void... voids) {
return (Serializable) worker.work(context);
}
}
FragmentAbleToStartTask
子类的例子:
public class NameListFragment extends FragmentAbleToStartTask {
private static final int TASK_REQUEST_CODE_RECEIVING_NAMES = 461;
private static final String KEY_PATTERN = "KEY_PATTERN";
private static final String KEY_NAMES = "KEY_NAMES";
private List<String> names;
private ListView listView;
public static Fragment newInstance(String patternToSearchNames) {
Fragment fragment = new NameListFragment();
Bundle args = new Bundle();
args.putString(KEY_PATTERN, patternToSearchNames);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.example_list_fragment, null);
listView = (ListView) root.findViewById(R.id.listView);
return root;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
startTaskReceivingNames();
} else {
restoreState(savedInstanceState);
}
}
// !!! Key Point
private void startTaskReceivingNames() {
String pattern = getArguments().getString(KEY_PATTERN);
TaskNotBeInterruptedDuringConfigurationChange task = new NamesReceiverTask(getActivity(), pattern);
startTask(TASK_REQUEST_CODE_RECEIVING_NAMES, task);
}
private void restoreState(Bundle savedInstanceState) {
names = (List<String>) savedInstanceState.getString(KEY_NAMES);
if (names != null) {
initList();
}
}
private void initList() {
setEmptyListView();
ArrayList<String> adapter = new ArrayList<String>(getActivity(), android.R.layout.simple_list_item_1, names);
listView.setAdapter(adapter);
}
private void setEmptyListView() {
View emptyListView = getView().findViewById(R.id.emptyListView);
listView.setEmptyView(emptyListView);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(KEY_NAMES, (Serializable) names);
}
// !!! Key Point
@Override
public void onTaskResult(int requestCode, int resultCode, Serializable result) {
if (requestCode == TASK_REQUEST_CODE_RECEIVING_NAMES) {
onReceivingNamesFinished(resultCode, result);
}
}
private void onReceivingNamesFinished(int resultCode, Serializable result) {
if (resultCode != Activity.RESULT_OK) {
getActivity().finish();
return;
}
this.names = (List<String>) result;
initList();
}
}