屏幕旋转后Fragment会被销毁两次?

我在一个Activity中加载一个fragment,当我旋转屏幕时该activity会重新建立,但里面的fragment不是应该也是跟随activity只销毁一次吗?为什么会销毁两次?

还有就是为什么有人讨论屏幕旋转fragment重叠问题?当activity销毁后,与其关联的fragment不也随之销毁了吗?再新建activity时也就一个fragment,何来重叠?

菜鸟表示很困惑,希望大神解决我的疑问,谢谢了!

MainActivity

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FragmentManager manager=getSupportFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        FragmentOne fragmentOne=new FragmentOne();
        transaction.replace(R.id.fragment_container,fragmentOne,"one");
        transaction.commit();

    }

FragmentOne

public class FragmentOne extends Fragment {

    private final String TAG=FragmentOne.class.getSimpleName();

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG,"onCreate");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View v=inflater.inflate(R.layout.fragment_one,container,false);

        Button button=v.findViewById(R.id.create_fragment);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager manager=getFragmentManager();
                FragmentTransaction transaction=manager.beginTransaction();
                transaction.replace(R.id.fragment_container,new FragmentTwo(),"two");
               // transaction.addToBackStack("one");
                transaction.commit();
            }
        });

        Log.i(TAG,"onCreateView");

        return v;

    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        Log.i(TAG,"onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.i(TAG,"onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();

        Log.i(TAG,"onDetach");
    }
}

生命周期输出

阅读 4.2k
1 个回答

1.为什么会出现重叠问题?
当屏幕旋转 Activity 销毁时会调用 onSaveInstanceState 方法(FragmentActivity中)

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        markState(getSupportFragmentManager(), Lifecycle.State.CREATED);
        Parcelable p = mFragments.saveAllState();//关键代码
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        ....
        
    }

mFragments.saveAllState()最终会把当前 FragmentManager 中管理的 Fragment 信息输入到 Parcelable 中并返回,具体的操作代码查看 FragmentManagerImpl.saveAllState()

Activity 恢复时

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);

        super.onCreate(savedInstanceState);
        ...
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);//关键代码
        }
        ...
}

mFragments.restoreAllState 最终调用的代码(FragmentManagerImpl)

void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
    ...
 for (int i=0; i<fms.mActive.length; i++) {
            FragmentState fs = fms.mActive[i];
            if (fs != null) {
                FragmentManagerNonConfig childNonConfig = null;
                if (childNonConfigs != null && i < childNonConfigs.size()) {
                    childNonConfig = childNonConfigs.get(i);
                }
                //重新实例化 Fragment
                Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig);
                if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
                //添加到FragmrntManager 中
                mActive.put(f.mIndex, f);
                // Now that the fragment is instantiated (or came from being
                // retained above), clear mInstance in case we end up re-restoring
                // from this FragmentState again.
                fs.mInstance = null;
            }
        }
    ...
}

可以看到 Fragment 被重新实例化并添加到 FragmentManger 中,并在稍后显示出来。此时如何你在 Activity 的 onCreate 中 再次执行 添加 Fragment 的事务,就会导致 Fragment 被添加两次。当Activity 被销毁时,与之关联的 Fragment 其实并没有被销毁,而是信息被保存起来,等到 Activity 恢复时重新实例化。

2.当我旋转屏幕时该activity会重新建立,但里面的fragment不是应该也是跟随activity只销毁一次吗?为什么会销毁两次?
当 Activity 销毁时 Fragment 也会被销毁,这是第一次。
当 Activity 恢复时 onCreate 中执行 replace ,注意在 replace 之前其实 FragmentManager 中已经有一个 Fragment 了,销毁时保存的 Fragment被恢复。执行 replace ,保存的 Fragment 被替换掉(执行 remove),并销毁掉,这是第二次。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题