setUserVisibleHint的使用.执行顺序和viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment
处理问题一:viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment的原因(源码解读);
处理问题二:setUserVisibleHint的使用场景和onCreate onResume() 的执行顺序
这个情况适合多个fragment之间切换时统计,而非activity和fragment同时交换,现在越来越多的应用会使用viewpager+fragment显示自己的内容页,fragment和activity有很多共同点。但是fragment和activity不同的是当调用本身的onResume和onPause方法的时候可能并不是当前的fragment在显示,例如当加载下面这张图时,当我打开MainActivity时显示的是第一个fragment 但此时调用的方法步骤如下:
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()
可见此时虽然用户看到的是第一个fragment 但第二个fragment onAttech onCreate onCreateView onActivityCreater onStart(“这个我没有打印log”)onResume 方法已经调用,这会导致如果我们要统计用户更喜欢哪个fragment的内容时,虽然fragment已经创建并且onResume但其实并没有显示这一页,那么是什么原因呢,这是因为Android v4包下的viewpager,为了让用户在切换过程中不会卡顿,谷歌官方默认当创建第一个fragment方法时回创建第二个fragment以确保用户滑动时第二个view已经被创建,保持viewPager的平滑滑动效果
翻阅谷歌api发现viewpager有一个方法即 setOffscreenPageLimit。但当在viewpager设置以下代码
viewPager.setOffscreenPageLimit(0);
运行时打印的log和上面完全一致,即就算你设置只加载一个fragment还是会加载第二个fragment,原因是setOffscreenPageLimit中的源码时这样写的
public void setOffscreenPageLimit(int limit) {
if (limit < DEFAULT_OFFSCREEN_PAGES) {
Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +
DEFAULT_OFFSCREEN_PAGES);
limit = DEFAULT_OFFSCREEN_PAGES;
}
if (limit != mOffscreenPageLimit) {
mOffscreenPageLimit = limit;
populate();
}
}
为了解决判断是否fragment当前显示问题 可以在fragment重写 setUserVisibleHint(boolean isVisibleToUser)
启动activity打印日志如下:
08-11 11:33:36.156 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:36.156 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-11 11:33:36.157 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()
当切换到第二个fragment时打印日志:
08-11 11:33:54.084 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
08-11 11:33:54.084 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:54.084 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
08-11 11:33:54.084 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onAttach
08-11 11:33:54.085 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreate
08-11 11:33:54.085 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
08-11 11:33:54.085 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
08-11 11:33:54.085 7162-7162/com.example.yinsgo.myui V/Fragment3﹕ onResume()
可见当fragment显示时回调用方法 setUserVisibleHint中的isVisibleToUser = true 当fragment被切换隐藏时回 isVisibleToUser = false;
所以当我们要统计是否用户看到一个fragment时可以执行一下代码
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
if (isVisibleToUser) {
//统计代码 或者 fragment显示操作
} else { }
}
今天又看了一下发现单纯的执行上面的代码是有问题的,因为如果我们在else中认为用户是离开界面其实是不对的,因为根据启动第一个Fragment的log日志
08-11 11:33:36.156 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-11 11:33:36.156 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-11 11:33:36.157 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-11 11:33:36.158 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-11 11:33:36.159 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-11 11:33:36.160 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-11 11:33:36.161 7162-7162/com.example.yinsgo.myui V/Fragment2﹕ onResume()
第一次setUserVisibleHint 方法 isVisibleToUser 是false 但其实这个时候只是还未初始化,并不是用户已经浏览界面准备离开,于是这里我们需要一个辅助标记变量具体代码如下:
/**
* 判断是否是初始化Fragment
*/
private boolean hasStarted = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
L.v(TAG, "setUserVisibleHint " + isVisibleToUser);
if (isVisibleToUser) {
hasStarted = true;
L.v(TAG,"开始界面");
} else {
if (hasStarted) {
hasStarted = false;
L.v(TAG,"结束界面");
}
}
}
当我们启动MainActivity时 Log打印如下:
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true
08-13 17:55:45.860 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 开始界面
08-13 17:55:45.860 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreateView
08-13 17:55:45.870 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onActivityCreated
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onResume()
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onAttach
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreate
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onCreateView
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onActivityCreated
08-13 17:55:45.880 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ onResume()
切换到第二个fragment时,此时离开第一个fagment log打印如下
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint false
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 结束界面
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint true
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 开始界面
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onAttach
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreate
08-13 17:57:04.310 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onCreateView
08-13 17:57:04.320 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onActivityCreated
08-13 17:57:04.320 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ onResume()
切换到第三个fragment时,此时离开第二个fragment log打印如下:
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ 结束界面
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ setUserVisibleHint true
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment3﹕ 开始界面
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onPause
08-13 17:58:15.040 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onStop
可见这样就可以准确统计用户是否离开或者开始浏览界面了。根据这些开始和离开可以统计用户停留界面的时间等数据。
总结:
viewPager.setOffscreenPageLimit(0)并没有什么用,因为goole为了用户更好的体验,已经在我们加载第一个fragment的时候默认同时又加载了第二个fragment,从源码中的设置可以看的出来。所以我们的这个设置不能起到任何作用;
setUserVisibleHint(页面的显示隐藏)的使用场景就是在framgment显示隐藏的时候进行一些操作(比如网络请求等),避免一个页面用户已经不可见了还在重复的加载数据,优化了性能。同时setUserVisibleHint在fragmnent的所有的生命周期之前调用,是最先执行的一个方法。所以我们应该在初始化的时候先进行一次网络请求,避免只在setUserVisibleHint显示的时候进行网络请求造成第一次进入页面的时候数据不加载的情况(因为刚进入一个页面的时候,setUserVisibleHint开始不显示,一会显示的时候我们开始网络请求,但是onCreateView()并没有执行,此时页面没有任何数据)。
(刚进入页面的时候生命周期的执行顺序)
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint false //setUserVisibleHint开始不显示
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment2﹕ setUserVisibleHint false //setUserVisibleHint开始不显示
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onAttach
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreate
08-13 17:55:45.850 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ setUserVisibleHint true //一会显示的时候我们开始网络请求,但是onCreateView()并没有执行
08-13 17:55:45.860 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ 开始界面
08-13 17:55:45.860 21467-21467/com.example.yinsgo.myui V/Fragment1﹕ onCreateView //onCreateView开始显示,记载布局
setUserVisibleHint的使用.执行顺序和viewPager.setOffscreenPageLimit(0)不管用还是默认会加载第二个fragment的更多相关文章
- Unity3D事件函数的执行顺序 - 包含渲染等模块的完整版,中英文对照
原文地址: http://www.cnblogs.com/ysdyaoguai/p/3746828.html In Unity scripting, there are a number of eve ...
- Javascript中页面加载完成后优先执行顺序
Javascript中页面加载完成后优先执行顺序 document优先于windowwindow优先于element //document加载完成执行方法体 document.addEventList ...
- Unity3D事件函数的执行顺序
In Unity scripting, there are a number of event functions that get executed in a predetermined order ...
- ViewPager+Fragment取消预加载(延迟加载)(转)
原文:http://www.2cto.com/kf/201501/368954.html 在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragmen ...
- ViewPager+Fragment取消预加载(延迟加载)
在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragment有个不好或者太好的地方.例如你在ViewPager中添加了三个Fragment,当加载V ...
- 从一个例子了解window.onload、$(function(){})、$(window).load(function(){})的加载顺序
最近遇到一个轮播需求: 1. ajax请求服务器,返回json,判断json数据里每一项中isFix属性是0还是1,0表示不轮播,1表示需要轮播. 2. 当isFix属性为0的时候,表示该图片不轮播, ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
- js的并行加载以及顺序执行
重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...
- Select查询执行顺序
链接:http://blog.jobbole.com/55086/ 很多程序员视 SQL 为洪水猛兽.SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言.面向对象的程序语 ...
随机推荐
- linux的chmod,chown命令 详解
指令名称 : chmod 使用权限 : 所有使用者 使用方式 : chmod [-cfvR] [--help] [--version] mode file... 说明 : Linux/Unix 的档案 ...
- 大话主席(superslide和 touchslide)插件的使用
对于实现效果来说,插件的办事效率真的是太高了,而且里边也被处理过兼容性,用起来实在是特别方便,现在我们来说说大话主席中的slide插件,它分为pc端(superslide)和移动端(touchslid ...
- ZBrush中的布料技巧分享
今天主要给大家介绍一种在ZBrush®3D图形绘制软件中创建特定类型的布料的技巧,这种方法简单却非常强大. 这个想法源自下面这张图: 我们今天所要讲的技巧可能不是实现复杂的服装设计最有效的方法,但确实 ...
- mongodb配置文件详解
logpath=/app/mongo/mongolog/mongo.log dbpath=/app/mongo/mongodata verbose = true #vvvv = true #此项会产生 ...
- Ubuntu18.04解决鼠标移动到Gnome顶栏左上角窗口不能平铺( Activites Overview 界面),和应用程序扩展不好用问题。
在用习惯了GNOME我们知道一个很好的功能就是通过鼠标移动到Gnome顶栏左上角后所有打开的窗口就会平铺在显示器上方便我们选不同的窗口(Activites Overview 界面),苹果MAC系统也有 ...
- 关于read函数的一些分析
ssize_t readn(int fd, std::string &inBuffer, bool &zero) { ssize_t nread = ; ssize_t readSum ...
- Node.js 指南(迁移到安全的Buffer构造函数)
迁移到安全的Buffer构造函数 移植到Buffer.from()/Buffer.alloc() API. 概述 本指南介绍了如何迁移到安全的Buffer构造函数方法,迁移修复了以下弃用警告: 由于安 ...
- Vue框架Element UI教程-axios请求数据
Element UI手册:https://cloud.tencent.com/developer/doc/1270 中文文档:http://element-cn.eleme.io/#/zh-CN gi ...
- Http请求和相应模式(B/S)(1)
B/S模式 服务器端的接受数据 :浏览器端 表单格式 <form></form> GET:请求方式, /index.html Web浏览器上的资源路径 uname=bjxt& ...
- HDU 4307 Contest 1
http://www.cnblogs.com/staginner/archive/2012/08/13/2636826.html 自己看过后两周吧,重新写了一遍.很受启发的.对于0.1,可以使用最小割 ...