问题分析


一直在简书里看别人的技术贴,今天我也来写点自己的心得!最近在写一个项目用到大量的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. 移动UI布局设计原则(一)

    学习笔记1 Learning notes one 移动UI布局设计的布局原则 Layout Principles of Mobile UI Layout Design 移动UI视觉交互设计法则 Des ...

  2. react与react-router

    路由在单页应用极其常见,不论是angularjs项目还是react项目,都有路由. 在react项目中使用路由,我们当然是全局安装react-router. 第一步: 第二步:创建几个要跳转到的页面 ...

  3. dijkstra 的优先队列优化

    既然要学习算法,就要学习到它的精髓,才能够使用起来得心应手. 我还是远远不够啊. 早就知道,dijkstra 算法可以用优先队列优化,我却一直不知道该怎样优化.当时,我的思路是这样的:假设有n个顶点, ...

  4. 求矩形面积(问题来自PythonTip)

    描述: 已知矩形长a,宽b,输出其面积和周长,面积和周长以一个空格隔开. 例如:a = 3, b = 8 则输出:24 22 方法一: a=int(input('')) //input返回的是字符串类 ...

  5. php循环删除文件夹和目录

    一定要注意文件夹中的两个目录---->   .(当前目录)  ..(上级目录) 需要对这两个目录进行过滤, 否则在删除或者遍历是会一直,对于..甚至会向你指定的文件夹的上级目录循环操作,删除重要 ...

  6. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  7. Bugly实现app全量更新

    转 http://blog.csdn.net/qq_33689414/article/details/54911895Bugly实现app全量更新 Bugly官网文档 一.参数配置 在app下的gra ...

  8. Dojo与jQuery综合比较分析

    最近一直都在参与项目,无法抽空写些或者看些东西,周末抽了点时间看了下关于Dojo和Jquery的东西,在CSDN上看到一篇两个框架进行对比的文章,感觉写的不错,就拿了过来,没有别的意思,一来想保留下来 ...

  9. MyBatis联合查询和使用association 进行分步式查询

    查询Emp的同时,查出emp对应的部门Department 方法1:联合查询,使用级联属性封装结果集 <!-- 联合查询,使用级联属性封装结果集 type:要自定义规则的javaBean类型 i ...

  10. linux系统--磁盘管理命令(一)

    一.基本命令 1.1 查看磁盘分区使用状况:df 参数: l:仅显示本地磁盘(默认) a:显示所有文件系统的磁盘使用情况,包括比如 /proc/ h:以1024进制计算最合适的单位显示磁盘容量 H:以 ...