Android开发之多Fragment切换优化

问题分析



一直在简书里看别人的技术贴,今天我也来写点自己的心得!最近在写一个项目用到大量的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
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

原文地址:https://www.cnblogs.com/Im-Victor/p/9556257.html

时间: 2024-11-10 07:15:09

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

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

本文来源:转载自: http://mobile.51cto.com/abased-410796.htm 在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitmap时,分给虚拟机中的图片的堆栈大小只有8M,如果超出了,就会出现OutOfMemory异常.所以,对于图片的内存优化,是Android应用开发中比较重要的内容. 1.要及时回收Bitmap的内存 Bitmap类有一个方法recycle(),从方法名可以看出意思是回收.这里就有疑问了,Android系

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

merge结合include优化android布局,效果不知道,个人感觉使用上也有很大的局限,不过还是了解一下,记录下来. 布局文件都要有根节点,但android中的布局嵌套过多会造成性能问题,于是在使用include嵌套的时候我们可以使用merge作为根节点,这样可以减少布局嵌套,提高显示速率. <?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://sch

Android开发之APN网络切换

本文介绍Android平台中关于APN网络切换的相关知识以及如何实现APN切换. 由于最近的项目中用到APN切换的功能,所以就借着这个机会介绍一下APN的相关知识及如何在Android实现切换过程.关于APN的基本知识我会在下面给大家介绍. 在这个示例中,我使用圆角ListView显示效果,关于Android实现ListView圆角效果,大家可以查看我以前的一篇博文:http://www.cnblogs.com/hanyonglu/archive/2012/03/18/2404820.html

Android开发之Fragment详解

Android开发之Fragment学习 1.简介: Fragment是Android 3.0引入的新API. Fragment代表了 Activity的子模块,因此可以把Fragment理解成Activity片段.Fragment用于自己的生命周期,也可以接受它自己的输入事件. Fragment必须被"嵌入" Activity中使用,因此虽然Fragment也拥有自己的生命周期,但Fragment的生命周期会受它所在的Activity的生命周期的控制.例如,当Activity暂停时,

Android开发之SQLite优化

本文原地址为:http://blog.csdn.net/horkychen/article/details/18892223 关于SQLite的优化,首先是能用SQL语句批次处理的,就不要单笔操作,Cursor就更是能不用就不用.比如成批的DELETE/UPDATE,将条件组装到SQL语句,会比使用CURSOR一条条的查再删效率要高很多(若干年前就曾使用存储过程代替单笔操作,将一次批量计算时间从一天缩到了数分钟以内,参考).其次是对操作的优化:对于INSERT/UPDATE操作较多时使用事务,如

android开发之Fragment加载到一个Activity中

Fragments 是android3.0以后添加的.主要是为了方便android平板端的开发.方便适应不同大小的屏幕.此代码是为了最简单的Fragment的使用,往一个Activity中添加Fragment,主要涉及的知识点有:1.Fragment类的创建,2.Fragment的添加3.无UI的 Fragment的添加,根据Tag找回Fragment Fragment对应的Xml布局文件, <LinearLayout xmlns:android="http://schemas.andro

Android开发之Navigationdrawer导航抽屉功能的实现(源代码分享)

导航抽屉(navigationdrawer)是一个从屏幕左边滑入的面板,用于显示应用的主要导航项目.用户可以通过在屏幕左边缘滑入或者触摸操作栏的应用图标打开导航抽屉.导航抽屉覆盖在内容之上,但不覆盖操作栏.当导航抽屉完全打开后,操作栏的标题需要更换为应用的名称,而不是显示当前视图的名称,并且关闭所有和当前视图相关的操作按钮.操作栏的"更多操作"菜单按钮不需要关闭,以保证用户可以随时访问"设置"和"帮助".下面我们就来实现导航抽屉的功能. Layo

Android开发之InstanceState详解

Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceState(),并且在介绍这两个方法之后,再分别来实现使用InstanceState保存和恢复数据功能.Android实现屏幕旋转异步下载效果这样两个示例. 首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Andr

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

Android开发之JNI(一)--HelloWorld及遇到的错误解析 1.NDK环境搭建 參考http://blog.csdn.net/xiaoliouc/article/details/8705560 2.HelloWorld编写 (1)新建一个AndroidprojectJniDemo,这个名字能够随便起. (2)新建一个HelloWorld.java类,里面的内容例如以下: public class HelloWorld { public native String print();