code小生,一个专注 Android 领域的技术平台

公众号回复 Android 加入我的安卓技术群

作者:DDDong丶
链接:https://www.jianshu.com/p/c8e8a0249911
声明:本文已获DDDong丶授权发表,转发等请联系原作者授权

问题分析

一直在简书里看别人的技术贴,今天我也来写点自己的心得!最近在写一个项目用到大量的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时发生了以下的生命周期:

image

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

废话不多说,亮出我的方法(抽取后的):

 /** *  Fragment的添加 * @param manager Fragment管理器 * @param aClass 相应的Fragment对象的getClass * @param containerId 容器的id * @param args 需要传值的话可将bundle填入  不需要传值就填null */protected void addFragment(FragmentManager manager, Class extends BaseFragment> aClass, int containerId, Bundle args) {

    String tag = aClass.getName();

    Logger.d("%s add fragment %s", TAG, aClass.getSimpleName());

    Fragment fragment = manager.findFragmentByTag(tag);

    FragmentTransaction transaction = manager.beginTransaction(); // 开启一个事务

    if (fragment == null) {// 没有添加        try {            fragment = aClass.newInstance(); // 通过反射 new 出一个 fragment 的实例

            BaseFragment baseFragment = (BaseFragment) fragment; // 强转成我们base fragment

            // 设置 fragment 进入,退出, 弹进,弹出的动画            transaction.setCustomAnimations(baseFragment.enter(), baseFragment.exit(), baseFragment.popEnter(), baseFragment.popExit());

            transaction.add(containerId, fragment, tag);

            if (baseFragment.isNeedToAddBackStack()) { // 判断是否需要加入回退栈                transaction.addToBackStack(tag); // 加入回退栈时制定一个tag,以便在找到指定的事务            }

        } catch (Exception e) {            e.printStackTrace();        }    } else {        if (fragment.isAdded()) {            if (fragment.isHidden()) {                transaction.show(fragment);            }        } else {            transaction.add(containerId, fragment, tag);        }    }

    if (fragment != null) {        fragment.setArguments(args);        hideBeforeFragment(manager, transaction, fragment);        transaction.commit();    }}

/** * 除当前 fragment 以外的所有 fragment 进行隐藏 * * @param manager * @param transaction * @param currentFragment */private void hideBeforeFragment(FragmentManager manager, FragmentTransaction transaction, Fragment currentFragment) {

    List fragments = manager.getFragments();for (Fragment fragment : fragments) {if (fragment != currentFragment && !fragment.isHidden()) {            transaction.hide(fragment);        }    }}

略微解释一下:

先查询fragmentManager 所在的activitiy 中是否已经添加了这个fragment
第一步 先从一个mAdded 的一个ArrayList遍历查找,如果找不到再从 一个 叫 mActive 的 SparseArray的一个map里面查找。

注意:

  1. 一个 fragment 被 remove 掉后,只会从 mAdded 里面删除,不会从 mActive 里面删除,只有当这个fragment 所在的 transaction 从回退栈里面移除后才会 从mActive 删除

  2. 当我们add 一个fragment时 会把我们的fragment 添加到 mAdded 里面,不会添加到 mActive。

  3. 只有当我们把 transaction 添加到回退栈的时候,才会把我们的 fragment 添加到 mActive 里面。所以我们通过 findFragmentByTag 方法查找出来的 fragment 不一定是被添加到我们的 activity 中。

使用:

代码比较多,但是我个人感觉使用起来比较方便,而且功能也比较完善,使用的时候只需要两行代码:

HomeFragment1 homeFragment = new HomeFragment1();addFragment(getSupportFragmentManager(),homeFragment.getClass(),R.id.main_body,null);

当我们需要传值的时候,只需要将准备好的bundle以参数的形式填入即可。
我还增加了一个是否加入回退栈的判断,用于实现一些有关回退栈的需求,实现这个功能还需要在BaseFragment中定义一个方法:

protected boolean isNeedToAddBackStack() {        return true;}

也就这么点内容,各位大佬如果看出什么问题或者有什么更好的方法,欢迎大家在下方评论留言。

推荐阅读
浅谈 Activity,Fragment 模块化封装
巧用 Fragment,解耦 Android6.0 权限适配手记

不怕巨人高

就怕巨人还要踩在巨人肩膀上

这样就很难超越了

android 为什么fragment在调用hide方法后没有生效_Android 多 Fragment 切换优化相关推荐

  1. 在android apk中调用@hide方法

    在android应用开发过程中我们经常会遇到不能使用,但却可以在源码中查到的方法,这些方法大多有/**@hide*/标记,如果想要调用hide方法或类我们就要重新打包sdk.如果有源码的话,可以去掉源 ...

  2. java调用一个方法后怎么继续执行不等待该方法的返回_Java面试题大全2020版(二)...

    今天给大家推送第二部分,主要的大块内容分为:多线程.反射.对象拷贝.三大块内容中涉及到的考点如下: 三.多线程 35. 并行和并发有什么区别? 并行是指两个或者多个事件在同一时刻发生:而并发是指两个或 ...

  3. android调用js函数方法,Android和JavaScript相互调用的方法

    本文实例讲述了Android和JavaScript相互调用的方法.分享给大家供大家参考,具体如下: Html页面和Java代码结合的方式一般用在界面经常被更改 的情况下,可以讲html放在网络中,软件 ...

  4. java关闭通道_调用map方法后,Java 7文件通道未正确关闭

    我正在研究一个sc2replay解析工具.我在MPQLIB http://code.google.com/p/mpqlib/之上构建它 不幸的是,该工具使用文件通道来读取bzip文件, 并使用map( ...

  5. Android之什么时候调用onSaveInstance方法的时候(为什么按Home键盘会调用,按Back不调用)

    1.函数介绍   1).onCreate(Bundle savedInstanceState) 方法 Activity 创建时回调 : 该方法会自动传入一个 Bundle 对象, 该 Bundle 对 ...

  6. android与H5交互调用js方法无效问题

    正常的调用js方法很简单,只有一句话 mWebView.loadUrl("javascript:do()"); do();是js提供的方法名 但是调用之后发现无效,不禁在想就这么一 ...

  7. html追加行clone,调用clone()方法后就可以将复制的节点追加到body元素内。( ) 答案:√...

    相关问题 以碳素钢为基础适量加入一种或几种合金元素的钢,具有较高的综合机械性能和某些特殊的物理.化学性能: 碳素钢 基础 合金 元素 钢 综合 机械 性能 物理 化学 性能 合金钢 下面关于数组长度的 ...

  8. android 连续调用方法是,android – SwitchPreferences多次调用onPreferenceChange()方法

    这是由于SwitchPreference实现中的错误. 调用onPreferenceChange回调: >第一次通过TwoStatePreference.onClick方法,它只更新Shared ...

  9. Android 使用MediaRecorder录音调用stop()方法的时候报错【转】

    本文转载自:http://blog.csdn.net/u014737138/article/details/49738827 这个问题在网上看到了太多的答案,一直提示说按照官网的api的顺序来,其实解 ...

最新文章

  1. linux apache web服务器
  2. C++ :vector的使用
  3. java for 死循环_简单的java死循环 java中的死循环问题
  4. 用ajax的方法获取列表,用ajax从服务器获取列表数据,为什么getElementsByTaName('li')的长度为0呢...
  5. 谈谈writev的问题
  6. php zhegnze_php 正则表达式
  7. C#中控件如何设置透明色
  8. 算法与数据结构(三) 二叉树的遍历及其线索化(Swift版)
  9. element表格动态列、本地分页、动态form、自定义校验集成
  10. linux vim看最低,linux vim
  11. 巧用安全IP策略指定计算机访问某台电脑
  12. AD19无法生成PCB_PCB制造拥抱AI
  13. 程序员,别再无脑刷题了,这样学 Python,编程能力暴增!
  14. 使用freemarker模板生成html文件(一)
  15. (百看不如一练系列)整理的40个前端练手项目|||实践出真知
  16. 【多标签文本分类】层次多标签文本分类方法
  17. YY语音CTO赵斌的技术创业
  18. 盘点一下文明与征服几个主流阵容搭配
  19. HTTP协议以及返回状态码
  20. c语言足球管理系统,如足球一般优美的C语言

热门文章

  1. 使用JGroups进行ElasticMQ消息复制
  2. Java应用程序上的Twitter API
  3. MacOS 常用命令汇总
  4. linux 划ext4,linux – 有没有像ext4这样的’快速’格式?
  5. python语言中的单行注释语句_Python 1基础语法一(注释、行与缩进、多行语句、空行和代码组)...
  6. 【开源项目】QT OPENGL 与 shader 绘制展示视频代码实例 OPenGL直接显示YUV数据
  7. opencv yuv保存本地_OpenCV-dlib-python3实现人脸戴墨镜和含Y的抖音效果
  8. android thrift https,HTTPS 学习
  9. UBUNtu·E: 无法获得锁 /var/lib/apt/lists/lock - open (11: 资源暂时不可用) E: 无法对目录 /var/lib/apt/lists/ 加锁 问题解决方法
  10. 工业以太网交换机在实际应用中的优势