我读了这个http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html。我在链接中播放了示例代码。令我惊讶的是,如果我在TaskFragment.onCreate()中删除setRetainInstance(true),当我旋转手机时,fm.findFragmentByTag(TAG_TASK_FRAGMENT)不会返回null。我在这里复制代码一行换行(删除setRetainInstance(true))。
请解释为什么fm.findFragmentByTag(TAG_TASK_FRAGMENT)在这种情况下不会返回null。
public class MainActivity extends Activity implements TaskFragment.TaskCallbacks {
private static final String TAG_TASK_FRAGMENT = "task_fragment";
private TaskFragment mTaskFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
FragmentManager fm = getFragmentManager();
mTaskFragment = (TaskFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);
if (mTaskFragment == null) {
mTaskFragment = new TaskFragment();
fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
}
}
@Override
public void onPreExecute() { }
@Override
public void onProgressUpdate(int percent) { }
@Override
public void onCancelled() { }
@Override
public void onPostExecute() { }
}
public class TaskFragment extends Fragment {
interface TaskCallbacks {
void onPreExecute();
void onProgressUpdate(int percent);
void onCancelled();
void onPostExecute();
}
private TaskCallbacks mCallbacks;
private DummyTask mTask;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallbacks = (TaskCallbacks) activity;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I remove this call to produce the problem
// setRetainInstance(true);
mTask = new DummyTask();
mTask.execute();
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
private class DummyTask extends AsyncTask<Void, Integer, Void> {
@Override
protected void onPreExecute() {
if (mCallbacks != null) {
mCallbacks.onPreExecute();
}
}
@Override
protected Void doInBackground(Void... ignore) {
for (int i = 0; !isCancelled() && i < 100; i++) {
SystemClock.sleep(100);
publishProgress(i);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... percent) {
if (mCallbacks != null) {
mCallbacks.onProgressUpdate(percent[0]);
}
}
@Override
protected void onCancelled() {
if (mCallbacks != null) {
mCallbacks.onCancelled();
}
}
@Override
protected void onPostExecute(Void ignore) {
if (mCallbacks != null) {
mCallbacks.onPostExecute();
}
}
}
}
答案 0 :(得分:1)
SetRetainInstance
控制整个片段(及其内容)是保留在内存中还是从Bundle
重新创建为新片段。
它返回null的唯一时间是应用程序第一次运行。之后它已添加到FragmentManager
并始终可用。 (无论您是否使用FragmentManager
,旋转设备都不会清除SetRetainInstance
您似乎认为SetRetainInstance
控制片段是否保留在FragmentManager
中。它没有。
在您的示例中,AsyncTask在第一次创建Fragment时开始运行。 SetRetainInstance用于停止正在调用的Fragment的OnDestroy方法。方向更改后,片段及其运行任务仍在FragmentManager中,任务仍在运行。如果没有SetRetainInstance,当Orientation发生更改时,从FragmentManager中检索片段时,片段将被销毁并从其bundle中重新创建。这使得AsyncTask处于一个微妙的状态,因为任务仍然可以运行,即使它的托管片段已被破坏可能导致崩溃。
请参阅此问题以获得更深入的解释。