Fragment的setUserVisibleHint方法实现懒加载,但setUserVisibleHint 不起作用?
我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个fragment都需要去加载数据,或从本地加载,或从网络加载,那么在这个activity刚创建的时候就变成需要初始化大量资源。这样的结果,我们当然不会满意。那么,能不能做到当切换到这个fragment的时候,它才去初始化呢?
答案就在Fragment里的setUserVisibleHint这个方法里。请看关于Fragment里这个方法的API文档:

该方法用于告诉系统,这个Fragment的UI是否是可见的。所以我们只需要继承Fragment并重写该方法,即可实现在fragment可见时才进行数据加载操作,即Fragment的懒加载。根据网友们提供的方法,代码如下(本人稍作修改了下):

1 import android.os.Bundle;
2 import android.support.v4.app.Fragment;
3
4 /**
5 * Author: wangjie
6 * Email: tiantian.china.2@gmail.com
7 * Date: 1/23/15.
8 */
9 public abstract class BaseLazyFragment extends Fragment {
10 private static final String TAG = BaseLazyFragment.class.getSimpleName();
11 private boolean isPrepared;
12
13 @Override
14 public void onActivityCreated(Bundle savedInstanceState) {
15 super.onActivityCreated(savedInstanceState);
16 initPrepare();
17 }
18
19
20 /**
21 * 第一次onResume中的调用onUserVisible避免操作与onFirstUserVisible操作重复
22 */
23 private boolean isFirstResume = true;
24
25 @Override
26 public void onResume() {
27 super.onResume();
28 if (isFirstResume) {
29 isFirstResume = false;
30 return;
31 }
32 if (getUserVisibleHint()) {
33 onUserVisible();
34 }
35 }
36
37 @Override
38 public void onPause() {
39 super.onPause();
40 if (getUserVisibleHint()) {
41 onUserInvisible();
42 }
43 }
44
45 private boolean isFirstVisible = true;
46 private boolean isFirstInvisible = true;
47
48 @Override
49 public void setUserVisibleHint(boolean isVisibleToUser) {
50 super.setUserVisibleHint(isVisibleToUser);
51 if (isVisibleToUser) {
52 if (isFirstVisible) {
53 isFirstVisible = false;
54 initPrepare();
55 } else {
56 onUserVisible();
57 }
58 } else {
59 if (isFirstInvisible) {
60 isFirstInvisible = false;
61 onFirstUserInvisible();
62 } else {
63 onUserInvisible();
64 }
65 }
66 }
67
68 public synchronized void initPrepare() {
69 if (isPrepared) {
70 onFirstUserVisible();
71 } else {
72 isPrepared = true;
73 }
74 }
75
76 /**
77 * 第一次fragment可见(进行初始化工作)
78 */
79 public abstract void onFirstUserVisible();
80
81 /**
82 * fragment可见(切换回来或者onResume)
83 */
84 public abstract void onUserVisible();
85
86 /**
87 * 第一次fragment不可见(不建议在此处理事件)
88 */
89 public abstract void onFirstUserInvisible();
90
91 /**
92 * fragment不可见(切换掉或者onPause)
93 */
94 public abstract void onUserInvisible();
95
96 }

如上代码,使用setUserVisibleHint方法作为回调的依据,
暴露出来让子类使用的新的生命周期方法为:
- onFirstUserVisible();
第一次fragment可见(进行初始化工作)
- onUserVisible();
fragment可见(切换回来或者onResume)
- onFirstUserInvisible();
第一次fragment不可见(不建议在此处理事件)
- onUserInvisible();
fragment不可见(切换掉或者onPause)
据说具体的效果是:
1. 首先加载ViewPager,回调FragmentA(第一个默认呈现的Fragment)的onFirstUserVisible(),可以在这里进行FragmentA的初始化工作,其他Fragment保持不变。
2. 用户从FragmentA滑动到FragmentB,回调FragmentA的onUserInvisible()、FragmentB的onFirstUserVisible()(因为第一次切换到FragmentB,可以在这里进行初始化工作)。
3. 用户从FragmentB滑动到FragmentC,回调FragmentB的onUserInvisible()、FragmentC的onFirstUserVisible()(因为第一次切换到FragmentC,可以在这里进行初始化工作)。
4. 用户从FragmentC滑动到FragmentB,回调FragmentC的onUserInvisible()、FragmentB的onUserVisible()(因为FragmentB之前已经被加载过)。
5. 因为到此为止,suoyou的Fragment都已经被加载过了,所以以后这3个Fragment互相任意切换,只会回调原来Fragment的onUserInvisible()和切换后的Fragment的onUserVisible()。
6. 用户处于FragmentB,关闭手机屏幕,回调FragmentB的onUserInvisible()。
7. 用户处于FragmentB,手机屏幕处关闭状态,然后开启手机屏幕解锁,只回调FragmentB的onUserVisible()。
可我TM无论怎么调试都没这个效果好吗,TMD setUserVisibleHint()就是不调用,不执行!!!
问度娘TMD都有是千篇一律的是使用fragment的setUserVisibleHint()方法实现懒加载,使用fragment的setuservisiblehint ()方法实现懒加载,使用fragment的setUserVisibleHint()方法实现懒加载;我去!!!我都快崩溃了好吗。
无果只能求助国外的网友了,竖上梯子问google(搜索 fragment setuservisiblehint not called)我的男神去了,打开第一条搜索结果,这个结果是我的另一个男神:
,这就是我正想要的,国外的网友给的答案如下:

答案大致意思是:需要 FragmentPagerAdapter 显示的对setUserVisibleHint()方法的调用,查看自己的adapter原来是继承的PagerAdapter 而不是FragmentPagerAdapter,于是果断重新生成一个继承 FragmentPagerAdapter 的 adapter,
代码如下:

1
3 import android.support.v4.app.Fragment;
4 import android.support.v4.app.FragmentManager;
5 import android.support.v4.app.FragmentPagerAdapter;
6
7 import java.util.ArrayList;
8 import java.util.List;
9
10 public class SimpleFragmentPagerAdapter extends FragmentPagerAdapter {
11 private List<Fragment> listFragments;
12 private List<String> mTitleList = new ArrayList<>();//页卡标题集合
13
14 public SimpleFragmentPagerAdapter(FragmentManager fm,
15 List<Fragment> al,
16 List<String> titleList) {
17 super(fm);
18 listFragments = al;
19 mTitleList = titleList;
20 }
21
22 public SimpleFragmentPagerAdapter(FragmentManager fm) {
23 super(fm);
24 }
25
26 @Override
27 public Fragment getItem(int position) {
28 return listFragments.get(position);
29 }
30
31 @Override
32 public int getCount() {
33 return listFragments.size();
34 }
35
36 @Override
37 public int getItemPosition(Object object) {
38 return super.getItemPosition(object);
39 }
40
41 @Override
42 public CharSequence getPageTitle(int position) {
43 return mTitleList.get(position);//页卡标题
44 }
45 }

然后将该adapter赋予Viewpager ,经调试成功了,setUserVisibleHint()方法终于起作用了,懒加载也有了。
项目源码:https://github.com/Leevey/LazyLoadFragment
参考文献:
实现类似微信的延迟加载的Fragment——LazyFragment
stackoverflow:Is Fragment.setUserVisibleHint() called by the android System?
Fragment的setUserVisibleHint方法实现懒加载,但setUserVisibleHint 不起作用?的更多相关文章
- Fragment的setUserVisibleHint方法实现懒加载
public abstract class LazyFragment extends Fragment { protected boolean isVisible; /** ...
- OC中重写set和get方法、懒加载
在写OC程序的时候,在很多时候我们会用到重写set或者get方法,重写这两个方法大多是用于刷新数据,比如懒加载. 意思就是说当你去调用set或者get方法时,系统会去调用重写的get或者set方法,这 ...
- swift 基础小结02 -- VFL约束、属性的get和set方法、懒加载、方法替换
一.属性的get和set方法 1.自定义属性的set和get方法 private(set) var _image:UIImage? //自定义属性get,s ...
- iOS之weak和strong、懒加载及循环引用
一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成 ...
- 【Java EE 学习 47】【Hibernate学习第四天】【sesion】【一级缓存】【懒加载】
一.Session概述 1.Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法. 2.理解Sessi ...
- hibernate懒加载(转载)
http://blog.csdn.net/sanjy523892105/article/details/7071139 懒加载详解 懒加载为Hibernate中比较常用的特性之一,下面我们详细来了解下 ...
- 关于懒加载(lazy loading)
懒加载---即为延迟加载,顾名思义在需要的时候才加载,这样做效率会比较低,但是占用内存低,iOS设备内存资源有限,如果程序启动使用一次性加载的方式可能会耗尽内存,这时可以使用懒加载,先判断是否有,没有 ...
- 【IOS学习基础】weak和strong、懒加载、循环引用
一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成 ...
- iOS开发基础-图片切换(4)之懒加载
延续:iOS开发基础-图片切换(3),对(3)里面的代码用懒加载进行改善. 一.懒加载基本内容 懒加载(延迟加载):即在需要的时候才加载,修改属性的 getter 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- [DLX反复覆盖] hdu 3656 Fire station
题意: N个点.再点上建M个消防站. 问消防站到每一个点的最大距离的最小是多少. 思路: DLX直接二分推断TLE了. 这时候一个非常巧妙的思路 我们求的距离一定是两个点之间的距离 因此我们把距离都求 ...
- Promise,Generator(生成器),async(异步)函数
Promise 是什么 Promise是异步编程的一种解决方案.Promise对象表示了异步操作的最终状态(完成或失败)和返回的结果. 其实我们在jQuery的ajax中已经见识了部分Promise的 ...
- Android的学习之路(三)项目的启动过程和安装过程具体解释
应用的安装和启动过程: 安装:第一步:java的编译器会把这个.java文件编译成.class文件 第二部:Android的SDK提供了一个dx工具,这个工具把.class文件转义 ...
- Drectx 3D窗口后台截图
//GDI与DX截屏API操作 LPDIRECTDRAW lpDD = NULL; LPDIRECTDRAWSURFACE lpDDSPrime = NULL; LPDIRECTDRAWSURFACE ...
- 连接ORACLE数据库,是不是必须要安装oracle客户端的运行时
大神给的回答: net连接oracle使用的是oci接口,必须安装oracle客户端,并配置本地网络服务名 tnsnames.ora.不过oracle网站有精简版的客户端软件,不到30M吧,解压,并编 ...
- SQL 中的语法顺序与执行顺序(转)
很多程序员都很抵触SQL.其实SQL是一整为数不多的声明性语言,只是它的运行方式完全不同于我们所熟知的命令行语言.面向对象的程序语言.甚至是函数语言. 今天大家共同学习下SQL的语法顺序与执行顺序.( ...
- SpringBoot打jar包问题
原文:https://jingyan.baidu.com/article/6f2f55a11d6e09b5b93e6c9e.html 当你使用springBoot进行打包的时候,这篇经验会帮助到你的. ...
- 腾讯Bugly2015年移动应用质量大数据报告 原 荐
在这份报告中,腾讯Bugly和腾讯优测会对2015年Android和iOS平台上的应用质量进行详细盘点,帮助你了解你的产品质量在行业中处于什么位置. 首先,让我们从整体上,回顾一下2015年度的应用和 ...
- 使用kubectl创建部署
本文使用自己利用VirtubalBox搭建的集群环境,暂时只有一个Master.一个Node.如果想了解集群的搭建,可以参考我的文章离线环境安装Kubernetes集群以及使用kubeadm安装kub ...
- [转]Hadoop Hive sql语法详解
转自 : http://blog.csdn.net/hguisu/article/details/7256833 Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式 ...