ViewpagerFragment懒加载

优化Android应用:Activity和Fragment数据加载策略 为了控制数据的加载,我们可以定义一个静态变量来标记当前的加载状态。这通常是一个枚举或者布尔类型的变量,例如或isLoading。在数据加载开始时,设置状态变量为true,表示正在加载。在数据加载结束后,根据结果将状态变量设置为false,表示加载完成。这样的状态标记在UI线程中读取,用于控制数据加载相关UI的显示和隐藏,比如进度条、空状态视图等。Loader的设计初衷是为了优化长时间运行的数据加载任务,并在Activity或Fragment的生命周期中对其进行管理。 阅读详情

老规矩,先来看看效果

ANDROID和福利两个Fragment是设置的Fragment可见时加载数据,也就是懒加载。圆形的旋转加载图标只有一个,所以,如果当前Fragment正处于加载状态,在离开该Fragment时需要隐藏加载动画,因为另一个Fragment并不一定处于加载状态,当返回Fragment时,如果还是处于加载状态,则要可以实现自动显示加载动画,如果数据已经加载完毕则不需要再显示出来。

以上效果就是今天要介绍和分享的,那么开始往下看吧。

懒加载

懒加载意思也就是当需要的时候才会去加载

那么,为什么Fragment需要懒加载呢,一般我们都会在onCreate()或者onCreateView()里去启动一些数据加载操作,比如从本地加载或者从服务器加载。大部分情况下,这样并不会出现什么问题,但是当你使用ViewPager + Fragment的时候,问题就来了,这时就应该考虑是否需要实现懒加载了。

ViewPager + Fragment 的坑

ViewPager为了让滑动的时候可以有很好的用户的体验,也就是防止出现卡顿现象,因此它有一个缓存机制。默认情况下,ViewPager会提前创建好当前Fragment旁的两个Fragment,举个例子说也就是如果你当前显示的是编号3的Fragment,那么其实编号2和4的Fragment也已经创建好了,也就是说这3个Fragment都已经执行完 onAttach() -> onResume() 这之间的生命周期函数了。

本来Fragment的 onResume()表示的是当前Fragment处于可见且可交互状态,但由于ViewPager的缓存机制,它已经失去了意义,也就是说我们只是打开了“福利”这个Fragment,但其实“休息视频”和“拓展资源”这两个Fragment的数据也都已经加载好了。

如果加载数据的操作都比较耗时或者都是类似图片的占用大量内存,这时就应该考虑想想是否该实现懒加载。也就是,当我打开哪个Fragment的时候,它才会去加载数据。

懒加载实现?

setUserVisibleHint(boolean isVisibleToUser) 可以?

当你去网上查找相关资料时,你会发现很多人推荐说把加载数据的操作放在这个函数里,isVisibleToUser表示当前Fragment是否可见。那么,是否真的可以就这样做呢?先来看个日志:

题主是从 DayDataFragment 跳转到 MeiziDataFragment 的,所以可以看到日志里面:DayDataFragment打出了false,表示它不可见了。而MeiziDataFragment却先打出了false,然后才打出true,这是因为setUserVisibleHint()在Fragment实例化时会先调用一次,并且默认值是false,当选中当前显示的Fragment时还会再调用一次。

所以,看上面的日志,除了DayDataFragment外,其他三个Fragment均没有实例化,所以当打开MeiziDataFragment时,因为ViewPager的缓存机制,会同时创建三个Fragment的实例,所以打印了三条isVisibleToUeser: false的日志,因为选中的是MeiziDataFragment,所以它还会触发一次setUserVisibleHint(),并且打印出true。

那么,是否可以在setUserVisibleHint(boolean isVisibleToUser)里进行数据加载操作来实现懒加载呢?

可以是可以,如果你只是需要数据的懒加载的话,但如果你还有以下的需求,那么这种方式就不行了:

1、如果你在Fragment可见时需要进行一些控件的操作,比如显示加载控件

2、如果你还需要在Fragment从 “可见 -> 不可见” 时进行一些操作的话,比如取消加载控件显示

这边再提一下,setUserVisibleHint()可能会在Fragment的生命周期之外被调用,也就是可能在view创建前就被调用,也可能在destroyView后被调用,所以如果涉及到一些控件的操作的话,可能会报 null 异常,因为控件还没初始化,或者已经摧毁了。

进一步封装

题主稍微进行了一些封装,自定义了一个新的回调函数onFragmentVisibleChange(boolean isVisible),可以实现的效果有:

1、只有两种情况会触发该函数

2、一种是Fragment从“不可见 -> 可见” 时触发,并传入 isVisible = true

3、一种是Fragment从“可见 -> 不可见” 时触发,并传入 isVisible = false

4、可以在该函数内进行控件的操作,不会报null异常

题主这次仍旧是从DayDataFragment 跳转到 MeiziDataFragment, 但跟上上面的日志图片不同,这里只打印了两条日志,也就是说即使有三个Fragment被实例化了,但只有显示的那个Fragment和离开的那个Fragment才会触发回调函数,这样就可以支持我们在可见状态变化时进行一些操作,因为不会有多余的false触发。

另外,因为ViewPager缓存机制,所以题主进行了view的复用,防止onCreateView()重复的创建view,其实也就是将view设置为成员变量,创建view时先判断是否为null。因为ViewPager里对Fragment的回收和创建时,如果Fragment已经创建过了,那么只会调用 onCreateView() -> onDestroyView() 生命函数,onCreate()和onDestroy并不会触发,所以关于变量的初始化和赋值操作可以在onCreate()里进行,这样就可以避免重复的操作。

代码


2016-04-21 更新:该博客封装的懒加载实现有些不足,比如不支持数据只有第一次打开Fragment时才进行加载的应用场景,因此重新写了篇博客,可以移步至此观看:再来一篇Fragment的懒加载(只加载一次哦)


最后附上代码,你也可以尝试自己进行封装下,代码很少,不到50行,理解思路就行了。


/**
 * Created by dasu on 2016/9/27.
 * https://github.com/woshidasusu/Meizi
 *
 * Viewpager + Fragment情况下,fragment的生命周期因Viewpager的缓存机制而失去了具体意义
 * 该抽象类自定义一个新的回调方法,当fragment可见状态改变时会触发的回调方法,介绍看下面
 *
 * @see #onFragmentVisibleChange(boolean)
 */
public abstract class ViewPagerFragment extends Fragment {

    /**
     * rootView是否初始化标志,防止回调函数在rootView为空的时候触发
     */
    private boolean hasCreateView;
    
    /**
     * 当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发
     */
    private boolean isFragmentVisible;
    
    /**
     * onCreateView()里返回的view,修饰为protected,所以子类继承该类时,在onCreateView里必须对该变量进行初始化
     */
    protected View rootView;

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        Log.d(getTAG(), "setUserVisibleHint() -> isVisibleToUser: " + isVisibleToUser);
        if (rootView == null) {
            return;
        }
        hasCreateView = true;
        if (isVisibleToUser) {
            onFragmentVisibleChange(true);
            isFragmentVisible = true;
            return;
        }
        if (isFragmentVisible) {
            onFragmentVisibleChange(false);
            isFragmentVisible = false;
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initVariable();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (!hasCreateView && getUserVisibleHint()) {
            onFragmentVisibleChange(true);
            isFragmentVisible = true;
        }
    }

    private void initVariable() {
        hasCreateView = false;
        isFragmentVisible = false;
    }

    /**************************************************************
     *  自定义的回调方法,子类可根据需求重写
     *************************************************************/

    /**
     * 当前fragment可见状态发生变化时会回调该方法
     * 如果当前fragment是第一次加载,等待onCreateView后才会回调该方法,其它情况回调时机跟 {@link #setUserVisibleHint(boolean)}一致
     * 在该回调方法中你可以做一些加载数据操作,甚至是控件的操作,因为配合fragment的view复用机制,你不用担心在对控件操作中会报 null 异常
     *
     * @param isVisible true  不可见 -> 可见
     *                  false 可见  -> 不可见
     */
    protected void onFragmentVisibleChange(boolean isVisible) {
        Log.w(getTAG(), "onFragmentVisibleChange -> isVisible: " + isVisible);
    }
}

用法

新建类ViewPagerFragment,将上面代码复制粘贴进去,添加需要的import语句 -> 新建你需要的Fragment类,继承ViewPagerFragment,在onCreateView()里对rootView进行初始化 -> 重写onFragmentVisibleChange(),在这里进行你需要的操作,比如数据加载,控制显示等。

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_android, container, false);
        
        }
        return rootView;
    } 
    
    @Override
    protected void onFragmentVisibleChange(boolean isVisible) {
        super.onFragmentVisibleChange(isVisible);
        if (isVisible) {
        //   do things when fragment is visible    
        //    if (ListUtils.isEmpty(mDataList) && !isRefreshing()) {
        //        setRefresh(true);
        //        loadServiceData(false);
            } else {
        //        setRefresh(false);
            }
        }
    }
  

构建Android:在Activity中动态加载及管理Fragment和数据交换实践 Fragment代表了Activity的一个片段。它拥有自己的布局和生命周期,允许开发者在运行时动态地添加、移除和替换。Fragment的引入,使得应用能够适应多种屏幕尺寸和设备配置,而不需修改Activity布局。FrameLayout是Android中最简单的布局之一,它的主要特点是它会将所有加入的子视图层叠起来,子视图会按照加入的顺序进行堆叠,后加入的视图会覆盖在之前的视图之上。 阅读详情

相关推荐

Android 关于fragment切换重新加载的解决方法

在项目中需要进行Fragment的切换,一直都是用replace()方法来替换Fragment 但是,这样会有一个问题 ,应该很多朋友都遇到过: 每次切换的时候,Fragment都会重新实例化,也就是运行OnCreatVIew()方法 那么如何让多个Fragment彼此切换时不重新实例化? 正确的切换方式是add(),切换时hide(),add()另一个Fragment,再次切换时,只需hide()当前,show()另一个。

Android图标库之SmallChart

Android图标库之SmallChart  SmallChart是一个开源的Android图表库,拥有5种不同的图表类型来展示数据。可以通过输入的数据以及可设置的颜色、画笔大小等属性方便的创建图表。 Github地址:https://github.com/Idtk/SmallChart 先来看看效果图吧~ SmallChart有以下几个特征: l  折线图、曲线图(可填充)、柱

绝不后退 2638

Android中Fragment的加载方式与数据通信详解

一、加载方式 1. 静态加载 1.1 加载步骤 (1) 创建fragment:创建自定义Fragment类继承自Fragment类,同时将自定义Fragment类与Fragment视图绑定(将layout转换成View) View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) inflater用于绑定Fragment的布局文件,同时将该布局转换成View对象并返回;container为Fragment的UI所在的父容器。返回值为Fragment显示的UI,若不显示,则返

android 分页加载坑,【Android】Fragment懒加载和ViewPager的坑

本篇文章已授权微信公众号 安卓巴士Android开发者门户 独家发布效果老规矩,先来看看效果效果图ANDROID和福利两个Fragment是设置的Fragment可见时加载数据,也就是懒加载。圆形的旋转加载图标只有一个,所以,如果当前Fragment正处于加载状态,在离开该Fragment时需要隐藏加载动画,因为另一个Fragment并不一定处于加载状态,当返回Fragment时,如果还是处于加载...

weixin_31421625的博客 230

Codex CLI 的多模型切换实战:如何在中转 API 环境下灵活选择最佳模型

本文详细介绍了在Codex CLI中实现多模型切换的实战技巧,重点解析了如何在中转API环境下灵活选择最佳AI模型。通过配置Node.js环境和智能路由策略,开发者可以根据任务类型、编程语言和成本考量,在GPT-5、Claude和DeepSeek等模型间高效切换,提升代码生成、审查和优化的效率。

weixin_29291185的博客 835

告别手动标注!PDMS NakiToolkit插件安装与初体验:以Pipeline工具为例

本文详细介绍了PDMS NakiToolkit插件的安装与使用,特别是其Pipeline工具如何通过自动化标注和材料统计功能大幅提升三维工厂设计效率。从环境准备到实战演示,帮助工程师告别繁琐的手动标注工作,实现项目交付周期的大幅缩短。

weixin_30047059的博客 349

android fragment加载数据,Android Fragment 懒加载实践

开发中,Fragment 最常见的两种使用方式就是 ViewPager 嵌套 Fragment ,以及直接通过FragmentManager 来管理 Fragment,对应的交互场景相信大家心里都有一个原型,没有的话也没关系,后边会有例子的。但这和懒加载有什么关系呢?试想一下,如果每个 Fragment 都有默认的网络请求操作(也可能是其它耗时操作,这里以网络请求为例),那么多个在 Fragmen...

weixin_35756130的博客 762

SAP OBYC自动过账全解析:从BSX到WRX的会计科目配置指南

本文深入解析SAP OBYC自动过账功能,从BSX到WRX的会计科目配置全流程,涵盖评估分组代码、事务码和评估类等核心概念。通过实战案例展示如何实现库存变动到财务过账的自动化流转,提升企业财务数据的准确性和效率。

weixin_29239279的博客 416

Viewpager Fragment懒加载

Viewpager Fragment懒加载Viewpager Fragment的懒加载包括两方面: 当页面对于用户可见时才请求数据 页面最多加载3个,即时销毁重建

sanlj的博客 405

树莓派与ROS2

树莓派与ROS2(Robot Operating System 2)的结合使用为机器人开发、自动化控制以及物联网项目提供了强大的平台。

weixin_47695827的博客 1754

深度剖析:Spring AI 与 LangChain4j,谁才是 Java 程序员的 AI 开发利器?

首先介绍 AI 时代 Java 开发框架选择背景,接着对比两者功能特性(Spring AI 的生态集成与标准化设计、LangChain4j 的多模型适配与提示工程)、应用场景(企业级系统改造与创新产品开发)、开发体验(学习成本与调试工具)、生态扩展(Spring 商业支持与 LangChain4j 开源社区)、性能安全(企业级优化与自主安全实现)及成本趋势(短期投入、长期回报与技术演进),最后给出选型建议与混合架构方案。

博客 5442

ViewPager懒加载(取消预加载)的实现

ViewPager大家经常用到的一个控件,经常会需要取消它的预加载功能。 下面贴一段代码可以完美实现懒加载功能,亲测可用。 首先需要写一个基类,所有需要懒加载的都继承这个类。这里只写了一些重要方法的实现,其他基类中的方法根据自己的需求添加 /** * * ViewPager + Fragment 结构中 * ViewPager 有预加载功能,在访问网络的时候会同时加载多个页面的网络,体...

Mr_Duoduo的博客 2023

IPv6之001-IPv6是什么

技术本质:IPv6(Internet Protocol version 6)是互联网工程任务组(IETF)设计的网络层核心协议,用于替代IPv4核心使命:解决IPv4地址枯竭问题,重构互联网基础架构,支撑万物互联时代革命性特征fill:#333;color:#333;color:#333;fill:none;IPv6128位地址空间无状态自动配置原生IPsec加密协议头部精简。

老韩的Linux云计算架构师进阶之路 1389

Fragment懒加载二次封装

懒加载 懒加载意思也就是当需要的时候才会去加载 那么,为什么Fragment需要懒加载呢,一般我们都会在onCreate()或者onCreateView()里去启动一些数据加载操作,比如从本地加载或者从服务器加载。大部分情况下,这样并不会出现什么问题,但是当你使用ViewPager + Fragment的时候,问题就来了,这时就应该考虑是否需要实现懒加载了。 ViewPager

laolongs的博客 435

NTC热敏电阻选型快速指南

NTC(Negative Temperature Coefficient Thermistor)负温度系数热敏电阻器,是由锰Mn,镍Ni,铜Cu,一氧化碳Co等烧结而成的氧化物。其电阻值随温度的升高而减小,即具有复温度系数,故被称为负温度系数热敏电阻。本文对热敏电阻的应用场景,结构特点和选型参数进行总结。

fydar的博客 1293

【EB-03】 AUTOSAR builder与EB RTE集成

打开EB工具后,在EB的步骤是:执行MultiTask(2)-> Mapping Component to Partitions(4)->Task Mapping(5)-> SvcAs_Trigger(7)-> Code Generation(8)如涉及新增BSW Module,也需要重复以上步骤。

libuping2023的博客 960

4-AVI--Fragment与ViewPager结合

零、前言 [1].认真看下图Fragment在ViewPager里的默认生命周期(可在浏览器中单独打开网页查看动图,清晰很多) [2].名字数据随机获取见:随机数据生成 [3].ViewPager的默认加载模式见: ViewPager的基本使用 [4].Fragment实现懒加载,ViewPager的实现见: ViewPager的基本使用 大...

张风捷特烈的博客 221

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

ViewPager + Fragment实现懒加载

ViewPager + Fragment实现懒加载标签(空格分隔): Android课程http://blog.youkuaiyun.com/tellh/article/details/50705178 http://www.jianshu.com/p/c5d29a0c3f4c推荐框架 https://github.com/lianghanzhen/LazyViewPager介绍懒加载,指的是必要的时候

白泽的博客 349

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

一个轮子搞定 Fragment 和状态栏那些事

今天给大家介绍一个开源库,看完后,很多 fragment 以及状态栏相关的烦恼将离你而去。 我不喜欢啰嗦,让我们直入主题吧。 搞定 fragment 那些事 fragment 有哪些烦恼? 动画不正常,尤其是有 fragment 嵌套的时候? can not perform this action after onSaveInstanceState 异常? 不正常的重影? 烦人的...

listenzz的博客 639

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

FastLib

基于Retrofit2.x及RxJava2.x的网络请求封装、网络请求与生命周期绑定、快速观察者、快速loading观察者、快速返回常用错误常用功能库二次封装方便调用:Glide加载图片封装、TabLayout+ViewPager Fragment切换封装、Logger日志打印封装多种常用界面布局:标题+多状态+下拉刷新+列表、标题+ViewPager等方便快速创建常用布局增加layout复用Fr

lll1230088的博客 317

viewpager fragment取消预加载 延时加载

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34270865的博客 95

ViewPager + Fragment 取消预加载

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34004750的博客 113

android fragment加载布局的方式,Android中Fragment的加载方式与数据通信详解

Android中Fragment的加载方式与数据通信详解发布时间:2020-08-22 18:55:57来源:脚本之家阅读:155作者:Joah一、加载方式1. 静态加载1.1 加载步骤(1) 创建fragment:创建自定义Fragment类继承自Fragment类,同时将自定义Fragment类与Fragment视图绑定(将layout转换成View)View onCreateView(Lay...

weixin_34475951的博客 2515

安卓基础之Fragment与ViewPager

viewPager与Fragment的组合方式是可以说是当前App开发的标配,所以放在一篇博客中进行描述。 Fragment Fragment是Acttivity界面一个组成部分,基本上目前使用到多个页面的情况下都会用到,其实Fragment最大的作用是分担Activity的代码压力,为了后期维护方便,不把所有的代码罗列到一个Activity中。 构建Fragment 1.Activity布局文件...

wygsqsj的博客 4154

Android Fragment+ViewPager 组合使用

Android Fragment+ViewPager 组合,一些你不可不知的注意事项 2016年12月26日 09:26:30亦枫Blog阅读数:2069 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/wenbitianxiafeng/article/details/53883587 前面两篇文章中,对 Fragment 的基本使用、...

行知致简的专栏 1万+
上一篇: 解决禁用IE设置代理检测不通过连不上网
下一篇: Android插件化和热修复简析
ChengLuo.
博客等级 码龄11年 144粉丝 35原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值