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 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- 关于GPL协议的理解(开源与商用、免费与收费的理解)
编者:请特别注意看暗红色粗体标注的那几句话,总结下来有下面几点: 如果你用了我的 GPL软件,那么你的软件也必须要开源,否则就不能使用我的软件,你是否把你的软件商用和我没关系 Oracle 卖的不是软 ...
- 用格式工厂将mts文件转换成其它格式flv,mpg失败
通常情况下,是由帧速率的改变引起的! 看一看你的MTS帧速率是多少,则转换成FLV时,帧速率要一样!---------- 这是非常重要的!!!
- Jenkins CI CD
原文:https://www.sunjianhua.cn/archives/jenkins-ci-cd.html 1.安装git 以下为简单应用,适合无gitlab服务器用户. #在git服务器(19 ...
- VisualStudio:如何监控 ADO.NET?
背景 很多场景下我们都需要监控 ADO.NET,如:查看某些框架(ORM)生成的 SQL.如何在不能使用 SQL Profile 的情况下监控 SQL 呢?VS 为我们提供了一个工具,本文做一些介绍! ...
- 深入浅出!从语义角度分析隐藏在Unity协程背后的原理
Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘.比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来 ...
- Kubernetes基础:Pod的详细介绍
本文的演练环境为基于Virtualbox搭建的Kubernetes集群,具体搭建步骤可以参考kubeadm安装kubernetes V1.11.1 集群 1. 基本概念 1.1 Pod是什么 Pod是 ...
- [转]cocos2d-x
Cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,使用 C++ 开发,基于OpenGL ES,基于Cocos2d-iphone,支持 WOPhone, iOS 4.1, Android 2. ...
- 数据库分库分表中间件:Mycat;分布式数据库;mysql的分布式事务
官网:http://mycat.io/,里面有电子书籍可以下载:http://www.mycat.io/document/mycat-definitive-guide.pdf 旧版本下载地址:http ...
- 在SqlServer 中解析JSON数据 [parseJSON] 函数 数据库中 解析JSON
使用如下: SELECT * FROM parseJSON('{ "联系人": { "姓名": "huang", "网名" ...
- 秒懂,Java 注解 (Annotation)你可以这样学
转自: https://blog.csdn.net/briblue/article/details/73824058 文章开头先引入一处图片. 这处图片引自老罗的博客.为了避免不必要的麻烦,首先声明我 ...