首页  编辑  

Android Fragment 多次调用OnCreateView以及切换页面后Fragment被销毁导致getActivity错误的问题

Tags: /Android/   Date Created:
Fragment onCreateView 多次被调用导致重复初始化,切换Fragment页面后, Fragment xxx not attached to a context 错误解决方法:
出现上面的问题主要是因为调用了
getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fragment_container, fragment)
                    .commit();
导致的,当FragmentManager在replace, remove等操作的时候,会把指定的fragment从activity中移除(detach),并且会销毁(即Fragment.onDestroy会被触发),所以下次重新add或者show的时候,就会重新创建该view了!
解决方法可以有:
1. 如果你的view中,没有绑定getActivity等使用Activity的活动,那么简单的方法就是在Fragment.onCreateView中用一个static变量保存创建的view:
private static View mView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    // mView 作为静态变量,防止切换到其他页面后,view被销毁导致getActivity()报错等
    // 下面的代码,直接防止切换其他页面回来后,重新初始化的问题
    if (mView == null) {
        mView = inflater.inflate(R.layout.fragment_data, null);
       // view的其他初始化代码,例如 btnOk = mView.findViewByID(R.id.ok);.....
  }
  return mView;
2. 如果你的Fragment中,有更新界面或者操作activity相关的东西,例如调用getActivity,那么detach后,已经没有activity了,哪怕你在onCreateView中保存了也无用!
最好的解决方法,使用下面的方法来切换view,即从FragmentManager中show/hide指定的Fragment,而不是remove,replace:
private Fragment curFrame;
private Fragment fragments[] = {new DataFragment(), new DeviceFragment(), new ReportFragment(), new SystemFragment()};
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = item -> {
            Fragment fragment = null;
            switch (item.getItemId()) {
                case R.id.navigation_data:
                    fragment = fragments[0];
                    break;
                case R.id.navigation_device:
                    fragment = fragments[1];
                    break;
                case R.id.navigation_report:
                    fragment = fragments[2];
                    break;
                case R.id.navigation_system:
                    fragment = fragments[3];
                    break;
            }
            return loadFragment(fragment);
        };
private boolean loadFragment(Fragment fragment) {
    if (fragment == null || curFrame == fragment) return false;

    // 下面代码从Activity中移除而不是销毁现有的fragment
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (curFrame != null) transaction.hide(curFrame);
    if (!fragment.isAdded()) transaction.add(R.id.fragment_container, fragment);
    transaction.show(fragment);
    transaction.commit();
    curFrame = fragment;
    return true;
}