Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 601|回复: 0

Android 关于Fragment重叠问题分析和解决

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-21 12:36:04 | 显示全部楼层 |阅读模式

    一、问题描述

    相信大家在使用Fragment的过程中,肯定碰到过Fragment重叠的问题,重启应用就好了。然而原因是什么呢?

    二、原因分析

    首先,Android管理Fragment有两种方式,使用add、hide、show的方式和replace方式,两种方式各有优缺点。

    1. replace方式 
      如果使用这种方式,是可以避免重叠的问题,但是每次replace会把生命周期全部执行一遍,如果在这些生命周期函数 里拉取数据的话,就会不断重复的加载刷新数据,所以我们并不推荐使用这种方式。

    2. add、hide、show的方式 
      虽然这种方式避免了可能重复加载刷新数据的问题,但是会出现重叠的问题。

    原因:

    当系统内存不足,Fragment 的宿主 Activity 回收的时候,Fragment 的实例并没有随之被回收。Activity 被系统回收时,会主动调用 onSaveInstance() 方法来保存视图层(View Hierarchy),所以当 Activity 通过导航再次被重建时,之前被实例化过的 Fragment 依然会出现在 Activity 中,此时的 FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。 
    然而我们还是推荐使用这个,我们可以解决。

    三、问题重现

    既然要解决问题,自然要重现一下! 
    1.手机的 “设置” - “开发者选项” - 打开”不保留活动”(主要用于模拟Activity被及时回收) 
    2.把 app 切换到后台,再重新打开,通过点按不同的 tab 来切换 Fragment 
    这里写图片描述

    四、解决方法

    方法一、简单暴力

    通过注释掉这句话,这样主 Activity 因为种种原因被回收的时候就不会保存之前的 fragment state

    @Override
    protectedvoidonSaveInstanceState(Bundle outState) {
    //如果用以下这种做法则不保存状态,再次进来的话会显示默认tab
    //总是执行这句代码来调用父类去保存视图层的状态
    //super.onSaveInstanceState(outState);
    }

    方法二、(推荐使用)

    重写onAttachFragment,重新让新的Fragment指向了原本未被销毁的fragment,它就是onAttach方法对应的Fragment对象

      @Override
        public void onAttachFragment(Fragment fragment) {
            if (tab1 == null && fragment instanceof Tab1Fragment)
                tab1 = fragment;
            if (tab2 == null && fragment instanceof Tab2Fragment)
                tab2 = fragment;
            if (tab3 == null && fragment instanceof Tab3Fragment)
                tab3 = fragment;
            if (tab4 == null && fragment instanceof Tab4Fragment)
                tab4 = fragment;
        }

    方法三

    思路同样是阻止系统恢复Fragment state,在FragmentActivity保存所有Fragment状态前把Fragment从FragmentManager中移除掉。

      protected void onSaveInstanceState(Bundle outState) {
            FragmentTransaction transaction = fm.beginTransaction();
            transaction.remove(tab1);
            transaction.remove(tab2);
            transaction.remove(tab3);
            transaction.remove(tab4);
            transaction.commitAllowingStateLoss();
            super.onSaveInstanceState(outState);
        }

    成功解决,ok,o(∩_∩)o ,希望可以帮助有需要的同学,如果觉得好,欢迎留个言啊!

    五、源码下载

    源码下载

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-12 15:44 , Processed in 0.068109 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表