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 方法. 注意:懒加载时一定要先判断该 ...
随机推荐
- GEF最简单的入门-helloword(1)
最近做插件项目.主要负责GEF这块. 好吧.资料真少的可以.特别是入门.都是一大堆一大堆的.网上最火的八进制的文章但对于我这种菜鸟级别看了还是一头雾水.各种资料折腾了半天.终于折腾出一个真正的入门例子 ...
- CSDN学院升级公告
CSDN学院将于2015年8月5日凌晨00:00-10:00进行停站升级,升级期间会影响大家的正常訪问和操作.给各位用户带来的不便敬请谅解. 升级结束后有不论什么问题请发邮件到webmaster@cs ...
- Spring Boot开发之流水无情(二)
http://my.oschina.net/u/1027043/blog/406558 上篇散仙写了一个很简单的入门级的Spring Boot的例子,没啥技术含量,不过,其实学任何东西只要找到第一个突 ...
- iOS webservice 接口使用方法
1.没有参数的webservice 接口,如下: 接口名:获取服务器时间 方法名: getServerTime() 参数:空 返回值:服务器当前时间: yyyy/MM/dd HH:mm:ss 使用方法 ...
- Java File.separator
在Windows下的路径分隔符和Linux下的路径分隔符是不一样的,当直接使用绝对路径时,跨平台会暴出“No such file or diretory”的异常. 比如说要在temp目录下建立一个te ...
- DataGridView 在 WinForms中应用不同的单元格式
/// <summary> /// Set the cell background colour to make the ups and downs more visible. /// & ...
- 网易游戏2015年暑期实习生面试经历-游戏研发project师
首先,我还是先介绍一下网易游戏吧.引用别人的一段话 作者:王选易.出处: http://www.cnblogs.com/neverdie/ 欢迎转载 .也请保留这段声明.假设你喜欢这篇文章,请点[推荐 ...
- 使用Spire.Office for .NET(Word、Excel、PPT、PDF等)的初步感受
前言 本文大部分内容来自http://www.codeproject.com/Articles/710747/First-thoughts-on-Spire-Doc-for-NET. 针对我个人来说, ...
- Android之一种很有趣的界面跳动提示动画
上一个效果图: ==================================== 先上布局: <RelativeLayout xmlns:android="http://sch ...
- 用jpinyin实现汉字转拼音功能
一.简介 项目地址:https://github.com/stuxuhai/jpinyin JPinyin是一个汉字转拼音的Java开源类库,在PinYin4j的功能基础上做了一些改进. [JPiny ...