我有一个带有两个片段的单一活动应用程序:
- 带有所有UI的片段;
- 没有视图的片段,
AsyncTask
作为其成员,并且setRetainInstance
设置为true。
目标是在activity被销毁后保持AsyncTask运行,并在应用程序恢复焦点时重用它。
我没有使用setTargetFragment
,所有片段之间的通信都是通过MainActivity
完成的。
我认为setRetainInstance
所做的是防止片段被重新创建,并保持完全相同的实例在我的处置,所以当我调用findFragmentByTag
时,重新创建一个被破坏的活动,它应该返回相同的保留实例,当它被创建,但这似乎不是情况。
结果是,我最终得到了一个在后台持续计数的noUi片段(我可以在调试器中看到私生子),另一个,重新创建了一个没有引用我正在运行的AsyncTask…
我做错了什么?
下面是一些代码:
public class MainActivity extends Activity
implements FragmentCounter.Callback, FragmentMainScreen.Callback {
private static final String TAG_MAINFRAGMENT = "TAG_MAINFRAGMENT";
private static final String TAG_COUNTERFRAGMENT = "TAG_COUNTERFRAGMENT";
private FragmentMainScreen mFragmentMain;
private FragmentCounter mFragmentCounter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
mFragmentMain = FragmentMainScreen.getInstance();
mFragmentCounter = FragmentCounter.getInstance();
getFragmentManager().beginTransaction()
.add(R.id.container, mFragmentMain, TAG_MAINFRAGMENT)
.add(mFragmentCounter, TAG_COUNTERFRAGMENT)
.commit();
} else {
mFragmentMain = (FragmentMainScreen) getFragmentManager()
.findFragmentByTag(TAG_MAINFRAGMENT);
//The fragment that gets returned here is not the same instance as the one
//I returned with getInstance() above.
mFragmentCounter = (FragmentCounter) getFragmentManager()
.findFragmentByTag(TAG_COUNTERFRAGMENT);
}
}
}
noGui片段:
public class FragmentCounter extends Fragment
implements CounterAsyncTask.Callback, FragmentMainScreen.Callback {
private Callback mListener;
private CounterAsyncTask mCounterTask;
public static FragmentCounter getInstance(){
return new FragmentCounter();
}
public interface Callback {
public void onData(int aValue);
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
if (activity instanceof Callback)
mListener = (Callback) activity;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return null;
}
@Override
public void onValueChanged(int value) {
//In the debugger, I can see this callback beeing called,
//even after my activity gets destroyed.
//The mListener is null since I set it that way in the onDetach to
//prevent memory leaks.
//The new activity has a different instance of this Fragment.
if (mListener != null)
mListener.onData(value);
}
@Override
public void startCounting(int from) {
mCounterTask = new CounterAsyncTask(this);
mCounterTask.execute(from);
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
}
AsyncTask:
public class CounterAsyncTask extends AsyncTask<Integer, Integer, Void>{
private int counter;
private Callback mListener;
private static final int SKIP = 5000;
public CounterAsyncTask(Callback listener) {
mListener = listener;
}
@Override
protected Void doInBackground(Integer...values) {
if (values != null)
counter = values[0];
while(!this.isCancelled()){
publishProgress(counter+=SKIP);
try{
Thread.sleep(SKIP);
}
catch(InterruptedException e){
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
mListener.onValueChanged(values[0]);
}
public interface Callback{
public void onValueChanged(int value);
}
}
提前感谢!
我错了。使用setRetainInstance,片段仅在配置更改时保留。因此,片段状态将在屏幕旋转时保持,或者如果活动在后台但而不是,如果活动被销毁。
要达到我想要的结果,我可能应该使用Service