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 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- Cloud Foundry中DEA启动应用实例时环境变量的使用
在Cloud Foundry v2中,当应用用户须要启动应用的实例时.用户通过cf CLI向cloud controller发送请求,而cloud controller通过NATS向DEA转发启动请求 ...
- [Winform]关于cefsharp触屏设备长按文本内容,崩溃问题的修复
摘要 在之前遇到cefsharp,在触屏电脑上,长按文本内容,会崩溃的问题. 相关文章 当时遇到这样的问题,在cefsharp项目下提交了bug.已经修复,可以参考当时我提的bug,以及解决过程,可参 ...
- EF+Sqlite 动态设置连接字符串
摘要 在做c/s项目的时候,如果使用ef+sqlite,我们不知道客户端会安装在哪里,需要动态的来设置db所在路径. 解决办法 /// <summary> /// 数据上下文 /// &l ...
- JavaScript学习总结(二十)——Javascript非构造函数的继承
一.什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人". var Chinese = { nation:'中国' }; 还有一个对象,叫做&qu ...
- TXMLDocument use case (Delphi)
Description This example illustrates the basic operations on an XML document. Code procedure CreateD ...
- firedac连接linux的oracle
firedac连接linux的oracle 首先要下载并安装 oci for linux.OCI的版本要和ORACLE数据库的版本一致. centos7环境下安装OCI:https://blog.cs ...
- Tomcat服务器集群与负载均衡实现
一.前言 在单一的服务器上执行WEB应用程序有一些重大的问题,当网站成功建成并开始接受大量请求时,单一服务器终究无法满足需要处理的负荷量,所以就有点显得有 点力不从心了.另外一个常见的问题是会产生单点 ...
- 使用VMWare虚拟机创建CentOS版本号的Linux学习环境(每一步都有截图与说明)
学习Android开发.假设不学习Linux的基本使用,总感觉心里过意不去,由于毕竟Android还是搭载在Linux的基础之上的. 因此.学习一种Linux系统的基本操作.对我们以后的学习还是非常有 ...
- 支持辉光效果的Label
支持辉光效果的Label 效果 源码 https://github.com/YouXianMing/UI-Component-Collection 中的 FBGlowLabel // // FBGlo ...
- redis实现秒杀demo
代码 package com.prosay.redis; import java.util.List; import redis.clients.jedis.Jedis; import redis.c ...