Android(安卓)Fragment重叠问题
前言:最近项目中用BottomNavigationView动态添加几个Fragment于FrameLayout中,bug就在我切换其他APP操作一会后,再回到当前APP,有很大概率出现fragment重叠的现象。
一、Fragment 重叠原因分析
切换到其他APP时,Android由于内存资源紧张,fragmen所在activity已经被销毁,但是保存了activity的状态:
Android有一个种特殊情况,就是app运行在后台的时候,内存资源紧张的时候导致把app的资源全部回收(销毁Activity),这时把app再从后台返回到前台时,app会重启Activity。
这属于非正常销毁,尽管Activity实例被销毁,但系统会调用Activity的onSaveInstanceState()保存其状态,这样,如果用户导航回该Activity,系统会使用onCreate中的参数savedInstanceStatea保存的状态数据恢复之前的fragment,并重新创建activity新实例,这样相当于又再次add了fragment进去,所以出现了重叠现象。
二、解决方案:(亲测有效)
findFragmentbyTag:
即在add()或replace()时绑定一个tag,一般用fragment的类名作为tag,然后在发生“内存重启”时,通过findFragmentByTag()
找到对应的Fragment显示show(),并hide()需要隐藏的fragment。
/*2、解决内存重启后碎片的重叠问题 */ private void initFragmen(Bundle savedInstanceState) { if(savedInstanceState != null) { // “内存重启”时调用 homepageFragment = (HomepageFragment)getSupportFragmentManager().findFragmentByTag("homepageFragment"); hotFragment = (HotFragment)getSupportFragmentManager().findFragmentByTag("hotFragment"); meFragment = (MeFragment)getSupportFragmentManager().findFragmentByTag("meFragment"); //取出onSaveInstanceState(Bundle outState)里保存离开时的那个界面的tag,恢复到用户离开时的那个Fragment的界面 String tag = savedInstanceState.getString("lastVisibleFragment"); switch (tag) { case "homepageFragment": // 解决重叠问题 getSupportFragmentManager().beginTransaction() .show(homepageFragment) .hide(hotFragment) .hide(meFragment) .commit(); break; case "hotFragment": // 解决重叠问题 getSupportFragmentManager().beginTransaction() .show(hotFragment) .hide(homepageFragment) .hide(meFragment) .commit(); topView.setVisibility(View.GONE); toolbar.setVisibility(View.GONE); break; case "meFragment": // 解决重叠问题 getSupportFragmentManager().beginTransaction() .show(meFragment) .hide(hotFragment) .hide(homepageFragment) .commit(); topView.setVisibility(View.GONE); toolbar.setVisibility(View.GONE); break; } } else { // 正常创建时 homepageFragment = new HomepageFragment(); hotFragment = new HotFragment(); meFragment = new MeFragment(); getSupportFragmentManager().beginTransaction() .add(R.id.content_fragment_layout,homepageFragment, "homepageFragment") .add(R.id.content_fragment_layout,hotFragment,"hotFragment") .add(R.id.content_fragment_layout,meFragment,"meFragment") .show(homepageFragment) .hide(hotFragment) .hide(meFragment) .commit(); } }
三、恢复到用户离开时的那个Fragment的界面
如果你想恢复到用户离开时的那个Fragment的界面,你还需要在onSaveInstanceState(Bundle outState)
里保存离开时的那个界面的tag或者下标,在“内存重启”代码块中,取出tag/下标,进行恢复。
/*5、内存销毁活动后,保存ctivity中当前显示的fragment的tag*/ @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); lastVisibleFragment = getVisibleFragment(); outState.putString("lastVisibleFragment",lastVisibleFragment.getTag()); }
四、得到Activity当前显示的fragment
/*6、得到当前Activity显示的fragment*/ private Fragment getVisibleFragment() { Fragment lastFragment = null; fragmentManager = getSupportFragmentManager(); fragmentList = fragmentManager.getFragments(); for(Fragment fragment : fragmentList) { if (fragment != null && fragment.isVisible()) { lastFragment = fragment; break; } } return lastFragment; }
更多相关文章
- 关于Android堆内存的设置
- Android之——性能与内存优化
- android从手机内存获得图片并全屏显示
- android 沉浸式状态栏不会和虚拟重叠
- Android(安卓)启动线程OOM
- android 內存等使用情況(转)
- Android缓存的引用
- Android模仿jquery异步请求
- Android(安卓)InputMethodManager泄漏Activity