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) {
if (mView == null) {
mView = inflater.inflate(R.layout.fragment_data, null);
}
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;
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;
}