当在 setRetainInstance 设置为 true 的片段上调用 ​​findFragmentByTag 时,不会返回相同的实例

When findFragmentByTag is called on a fragment with setRetainInstance set to true, the same instance is not returned

我有一个包含两个片段的 activity 应用程序:

  1. 包含所有UI的片段;
  2. 没有视图的片段,其成员为 AsyncTask,并且 setRetainInstance 设置为 true。

目标是即使在 activity 被销毁后仍保留 AsyncTask 运行,并在应用程序恢复焦点时重用它。

我没有使用 setTargetFragment,片段之间的所有通信都是通过 MainActivity 完成的。

我认为 setRetainInstance 所做的是防止片段被重新创建并保留完全相同的实例供我使用,因此当我调用 findFragmentByTag 重新创建已销毁的 activity 时,它应该 return 与创建时相同的保留实例,但情况似乎并非如此。

结果是我得到了一个在后台不断计数的 noUi 片段(我可以在调试器中看到这个混蛋),以及另一个没有引用我的 运行 异步任务...

我做错了什么?

这是一些代码:

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;
}
}

异步任务:

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 时, 配置 更改时保留片段。因此,片段状态将在屏幕旋转时保持,或者如果 activity 在后台但 而不是 如果 activity 被破坏。

为了达到我想要的结果,我可能应该使用服务。