一 基本使用
Fragment依附于Activity使用,方面我们在一个页面里面切换显示多屏内容。
Activity管理Fragment有两种方式,通过FragmentTransacation这个类来管理fragment的显示、隐藏
1 replace方法
1 FragmentTransaction transaction = mBaseActivity.getSupportFragmentManager().beginTransaction(); 2 transaction.replace(R.id.fl_container, mCurrent).commit();
使用这种方法,可以避免出现fragment重叠问题。但每次执行replace时,fragment都会重新走一遍生命周期方法,会造成重复加载数据。不推荐使用。
2 hide,show,add方法
1 private void switchFragment(Fragment from, Fragment to) { 2 if (mCurrent != to) { 3 mCurrent = to; 4 FragmentTransaction transaction = mBaseActivity.getSupportFragmentManager().beginTransaction(); 5 // 判断目标fragment是否被add过 6 if (!to.isAdded()) { 7 transaction.hide(from).add(R.id.fl_container, to,to.getClass().getName()).commit(); 8 } else { 9 transaction.hide(from).show(to).commit(); 10 } 11 } 12 }
使用这种方法,避免了重新加载数据问题,但是会出现fragment重叠问题。
原因:当内存不足时,系统会回收宿主Activity,而Fragment实例并没有被一并回收,activity被回收时会主动调用onSaveInstanceState方法,保存视图层(View Hierarchy)及一些activity的数据。
二 重叠问题
通过onCreate中的参数savedInstanceState恢复了之前的fragment。此时的FragmentTransaction中的相当于又再次add了fragment进去的,之前保存的fragment也还在。hide()和show()方法对之前保存的fragment已经失效了。之前显示的fragment一直显示,所以出现了重叠的现象。解决方法:
首先,activity被系统收回,触发onSaveInstanceState(Bundle outState)方法,在outstate里,系统自动保存了fragment数据,手动保存当前显示的fragment索引
1 private static final String SAVED_CURRENT_ID = "currentId"; 2 private int currentIndex; 3 @Override 4 public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { 5 outState.putInt(SAVED_CURRENT_ID, currentIndex);//保存当前显示fragment索引 6 super.onSaveInstanceState(outState, outPersistentState); 7 }
其次,当重新进入activity时,走生命周期方法oncreae(Bundle savedInstanceState),saveInstanceState 包含了fragment数据,以及其他一些view的状态,和我们手动保存的数据,从bundle里取出fragment对象,避免重新实例化fragment,造成视图重叠
1 @Override 2 protected void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState); 4 setContentView(R.layout.activity_main); 5 //重启时防止fragment重叠 6 if (savedInstanceState != null) { 7 currentIndex = savedInstanceState.getInt(SAVED_CURRENT_ID, 0); 8 homeFragment = (HomeFragment) getSupportFragmentManager().findFragmentByTag(HomeFragment.class.getName()); 9 newsFragment = (NewsFragment) getSupportFragmentManager().findFragmentByTag(NewsFragment.class.getName()); 10 findFragment = (FindFragment) getSupportFragmentManager().findFragmentByTag(FindFragment.class.getName()); 11 adminFragment = (AdminFragment) getSupportFragmentManager().findFragmentByTag(AdminFragment.class.getName()); 12 } else { 13 initFragment(); 14 } 15 intView(); 16 } 17 18 @Override 19 protected void intView() { 20 setTitle("主页");23 radioGroup = (RadioGroup) findViewById(R.id.rg_main_bottom); 24 radioGroup.setOnCheckedChangeListener(occl); 25 ((RadioButton) radioGroup.getChildAt(currentIndex)).setChecked(true); 26 }
最后,恢复选中fragment
1 private RadioGroup.OnCheckedChangeListener occl = new RadioGroup.OnCheckedChangeListener() { 2 3 @Override 4 public void onCheckedChanged(RadioGroup group, int checkedId) { 5 switch (checkedId) { 6 case R.id.rb_home: 7 setTitle("首页"); 8 currentIndex = 0; 9 if (homeFragment == null) { 10 homeFragment = HomeFragment.newInstance(null, null); 11 } 12 switchFragment(mBackHandledFragment, homeFragment); 13 break; 14 case R.id.rb_news: 15 setTitle("新闻"); 16 currentIndex = 1; 17 if (newsFragment == null) { 18 newsFragment = NewsFragment.newInstance(null, null); 19 } 20 switchFragment(mBackHandledFragment, newsFragment); 21 break; 22 case R.id.rb_find: 23 showTabSelectView(); 24 currentIndex = 2; 25 if (findFragment == null) { 26 findFragment = FindFragment.newInstance(null, null); 27 } 28 switchFragment(mBackHandledFragment, findFragment); 29 break; 30 case R.id.rb_admin: 31 setTitle("我的"); 32 currentIndex = 3; 33 if (adminFragment == null) { 34 adminFragment = AdminFragment.newInstance(null, null); 35 } 36 switchFragment(mBackHandledFragment, adminFragment); 37 break; 38 } 39 } 40 }; 41 43 private void switchFragment(Fragment from, Fragment to) { 44 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 45 if (null == from) { 46 if (mBackHandledFragment != to) { 47 mBackHandledFragment = (BackHandledFragment) to; 48 if (!to.isAdded()) { 49 transaction.add(R.id.frameLayout_container, to, to.getClass().getName()).commit(); 50 } else { 51 transaction.show(to).commit(); 52 } 53 } 54 } else { 55 if (mBackHandledFragment != to) { 56 mBackHandledFragment = (BackHandledFragment) to; 57 // 判断目标fragment是否被add过 58 if (!to.isAdded()) { 59 transaction.hide(from).add(R.id.frameLayout_container, to, to.getClass().getName()).commit(); 60 } else { 61 transaction.hide(from).show(to).commit(); 62 } 63 } 64 } 65 }
原文地址:https://www.cnblogs.com/suiyilaile/p/9084279.html