问题分析


一直在简书里看别人的技术贴,今天我也来写点自己的心得!最近在写一个项目用到大量的Fragment后的总结!

我想刚刚接触安卓的同学或许会这么写:

FragmentManager     fragmentManager=getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.add(ViewId,fragment);// 或者fragmentTransaction.replace(ViewId,fragment);
fragmentTransaction.commit();

基础更好一点的同学会用show和hide方法

  FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.hide(new FirstFragment())
.show(new SecondFragment())
.commit();

诚然这两种都可以切换Fragment,但是面对用户大量点击来回切换,或者你的Fragment本来就很多,每次都这样操作,那么很快你的应用就会OOM,就算不崩那也会异常的卡顿!so why?

当我们replace时发生了以下的生命周期:

 
 

想想看每次都replace一下!!这世界会有多美好!!!那么问题出在哪?回过头看看代码就会发现每次在add/replace或者show/hide都会new 一个新的实例,这就是致命原因!!!!!

废话少说,开始优化


方案一:

预加载模式:

//首先需要先实例好三个全局Fragment

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment, FirstFragment.getInstance());
ft.add(R.id.fragment, SecondFragment.getInstance());
ft.add(R.id.fragment, ThirdFragment.getInstance());
ft.hide(SecondFragment.getInstance());
ft.hide(ThirdFragment.getInstance());
ft.commit();

在加载第一个Fragment时就把全部Fragment加载好,下次使用直接调用如:

FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.hide(FirstFragment.getInstance())
       .show(SecondFragment.getInstance())
       .commit();

是不是总觉怪怪的,虽然比之前的代码好,但是这种做法很Java,当然需要预加载的朋友依然是不二之选!!!

那有没有更好的方法呢?答案是肯定的

方案二:

动态加载模式:

//首先需要先实例好n个全局Fragment

//private  Fragment  currentFragment=new Fragment();(全局)

private  FragmentTransaction switchFragment(Fragment targetFragment) {

   FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
if (!targetFragment.isAdded()) {
//第一次使用switchFragment()时currentFragment为null,所以要判断一下
if (currentFragment != null) {
transaction.hide(currentFragment);
}
transaction.add(R.id.fragment, targetFragment,targetFragment.getClass().getName()); } else {
transaction
.hide(currentFragment)
.show(targetFragment); }
currentFragment = targetFragment;
return transaction;
} 在点击切换Fragment时: @Override
public void onTabSelected(@IdRes int tabId) { if (tabId == R.id.tab_one){ switchFragment(first).commit(); }
if (tabId == R.id.tab_two){
switchFragment(second).commit();
}
if (tabId == R.id.tab_three){
switchFragment(third).commit();
}
}

现在你的Fragment无论怎么切都不会出现卡顿了,因为你的所有Fragment只会被实例化一次!实例一次的Fragment会被存入内存中,下次切换会判断内存中是否含有要切换的Fragment,如果有就直接复用,没有就add一个新的!优化大法完成!

外番


WHAT?等等!只实例一次,那我的Fragment里的数据要更新怎么办?我的回答是——软件关了再次重启!

 
 

要是这样,这样的软件真的要逆天了!好在官方提供了onHiddenChanged方法,每次切换hide或者show时该方法会被执行,可以在这里面更新数据!

//此方法在Fragment中

@Override
public void onHiddenChanged(boolean hidden) {
   super.onHiddenChanged(hidden);
   if (hidden){
      //Fragment隐藏时调用
   }else {
       //Fragment显示时调用
   }

}

此方法是不是比每次add或replace更新数据执行一大坨的生命周期要优雅的多的多!

GitHub地址:FragmentDemo (欢迎 fork 和 star)

注:提醒小白(老手请忽略)

此demo只供fragment理解,此样例app的业务逻辑建议ViewPager+Fragment或者其他。。。

作者:8金木研8
链接:https://www.jianshu.com/p/4c5f015b3b6c
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

Android开发之多Fragment切换优化的更多相关文章

  1. 【转】Android开发之Bitmap的内存优化详解

    本文来源:转载自: http://mobile.51cto.com/abased-410796.htm 在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitma ...

  2. android开发之merge结合include优化布局

    merge结合include优化android布局,效果不知道,个人感觉使用上也有很大的局限,不过还是了解一下,记录下来. 布局文件都要有根节点,但android中的布局嵌套过多会造成性能问题,于是在 ...

  3. Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab

     今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...

  4. Android开发之InstanceState详解

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  5. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  6. Android开发之InstanceState详解(转)---利用其保存Activity状态

    Android开发之InstanceState详解   本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...

  7. Android开发之eclipse 快捷键

    转自:<Android开发之eclipse 快捷键>http://www.cnblogs.com/aimeng/archive/2012/08/07/2626909.html Ctrl+1 ...

  8. Android开发之旅3:android架构

    引言 通过前面两篇: Android 开发之旅:环境搭建及HelloWorld Android 开发之旅:HelloWorld项目的目录结构 我们对android有了个大致的了解,知道如何搭建andr ...

  9. Android开发之JNI(一)--HelloWorld及遇到的错误解析

    Android开发之JNI(一)--HelloWorld及遇到的错误解析 1.NDK环境搭建    參考http://blog.csdn.net/xiaoliouc/article/details/8 ...

随机推荐

  1. 描述符__get__(),__set__(),__delete__()(三十七)

    http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__ ...

  2. 证明最大公约数Stein算法(高精度算法)

    E:even 奇数  O:odd 偶数 若(a,b)为(e,e),则gcd(a,b)=2*gcd(a/2,b/2) 若(a,b)为(e,o),则gcd(a,b)=gcd(a/2,b) 若(a,b)为( ...

  3. kubectl命令自动补全

    kubectl这个命令行工具非常重要,与之相关的命令也很多,我们也记不住那么多的命令,而且也会经常写错,所以命令自动补全是非常有必要的,kubectl命令行工具本身就支持complication,只需 ...

  4. 10、JPA-二级缓存

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

  5. C#中子线程操作主线程中窗体上控件的方法

    Demo this.listView1.Visible = true; this.listView1.BeginUpdate();this.listView1.EndUpdate(); //结束数据处 ...

  6. cdqz2017-test8-Tree(点分树)

    n个点的带点权带边权的树,设点权为a[i],边权为b[i] 一棵树有n*(n-1)/2个点对, 定义这棵树的价值为任意两点对的(a[x]^a[y])*dis(x,y) 有m次修改一个点的点权的操作 输 ...

  7. bzoj千题计划299:bzoj1856: [Scoi2010]字符串

    http://www.lydsy.com/JudgeOnline/problem.php?id=1856 卡特兰数 从(1,1)走到(n,m),不能走y=x 上方的点,求方案数 从(1,1)走到(n, ...

  8. 任意两点间的最短路问题(Floyd-Warshall算法)

    #define _CRT_SECURE_NO_WARNINGS /* 7 10 0 1 5 0 2 2 1 2 4 1 3 2 2 3 6 2 4 10 3 5 1 4 5 3 4 6 5 5 6 9 ...

  9. 12. SpringBoot国际化

    1).编写国际化配置文件: 2).使用ResourceBundleMessageSource管理国际化资源文件 3).在页面使用fmt:message取出国际化内容 步骤:1).编写国际化配置文件,抽 ...

  10. Linux 开机启动图形界面,shell界面

    查看当前启动模式 # systemctl get-default 更改模式命令: systemctl set-default graphical.target由命令行模式更改为图形界面模式 syste ...