关于ViewPager设置属性页setCurrentItem会阻塞主线程ANR总结
关于android开发设置View Pager的直接跳转页set CurrentItem会阻塞主线程ANR。
根据网上解决的说法,分析源码:
if (mFirstLayout) {
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
是因为主线程测量滑动距离,绘制UI阻塞,因此通过反射拿到 mFirstLayout变量,每次在setCurrentItem的代码之前设置为true,
try {
Field mFirstLayout = ViewPager.class
.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(vpImg, true);
vpImg.setCurrentItem(num + numCenter, false);
} catch (Exception e) {
e.printStackTrace();
}
根据以上解决方法本应能够解决ANR,可事实依然存在问题,上码:
@Override
public int getCount() {
tvPicSum.setText(vpImg.getCurrentItem() % mOrderListPic.size() +
1 + "/"
+ mOrderListPic.size());
if (mOrderListPic.size() >= 2) {// 当条目超过一个
return Integer.MAX_VALUE;
}
return mOrderListPic.size();
}
这是我的适配器PagerAdapter的getCount()方法,为了能够实现ViewPager的近似无限轮播效果,我们将viewPager的限制页数设置为Integer类型的最大值,但也从而会使ViewPager在setCurrentItem时测量页数太大,绘制UI频繁而阻塞主线程ANR,因此我将数量改成了相对较小些mOrderListPic.size()*40。问题便得带了根本的解决。
版权声明:本文为博主原创文章,未经博主允许不得转载。
项目需求有无限轮播图,之前一直用的没问题,就用之前的放上去了,但是,有个需求是刷新时,把轮播图位置复位,心想不就是setCurrentItem么,so easy!
但....事情却没有那么简单
大家都知道,无限轮播图的做法就是把Adapter中重写getCount返回一个很大的数字,欺骗viewpager有很多,在对position和数据size取模,使数据的position和实际的position对应上,然后使用的时候把当前position设置到getCount数值 的中间,所以setAdapter后setCurrentItem(...),ok,到这里一切顺利
当页面刷新时,得到新数据,对viewpager重新设置数据,然后再次setCurrentItem恢复到初始位置时,问题就来了,这时整个页面完全卡死,过一会就ANR了
懵了......
这么简单的问题竟然会有问题
好了,开始解决问题
经过调试,问题代码就出现在setCurrentItem这行代码,查看ViewPager源码,发现最终调用到这个方法:
void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {}
方法里面有行判断:
if (mFirstLayout) {
// We don't have any idea how big we are yet and shouldn't have any pages either.
// Just set things up and let the pending layout handle things.
mCurItem = item;
if (dispatchSelected) {
dispatchOnPageSelected(item);
}
requestLayout();
} else {
populate(item);
scrollToItem(item, smoothScroll, velocity, dispatchSelected);
}
mFirstLayout是一个私有变量,默认为true,第一次设置数据时,mFirstLayout为true,然后在viewpager的
onLayout方法中就被设置成了false
当下次再次setCurrentItem时就进入了else中,这时,else中的代码就会引起UI卡顿,具体原因还未深入研究
但到这就有了思路了,可以利用反射,强行修改mFirstLayout的值为true
try {
Field mFirstLayout = ViewPager.class.getDeclaredField("mFirstLayout");
mFirstLayout.setAccessible(true);
mFirstLayout.set(vp_top, true);
myPagerAdapter.notifyDataSetChanged();
vp_top.setCurrentItem(Integer.MAX_VALUE/4-( Integer.MAX_VALUE/4 % ids_list_data.size() ));
}catch(Exception e) {
e.printStackTrace();
}
好了,到这里问题解决
ps 中间考虑过的方法还有一种,就是获取当前position,经过判断需要位移多受啊能到初始位置,就在刷新时偏移多少,但
是经测试,发现一个问题,在
vp_top.setCurrentItem(vp_top.getCurrentItem()+1);这样偏移一个单位时是没问题的,但是大于1就会卡顿,这个原因
不是很清楚,可能还是跟view的实例化有关,还需要深入研究
关于ViewPager设置属性页setCurrentItem会阻塞主线程ANR总结的更多相关文章
- Kafka producer异步发送在某些情况会阻塞主线程,使用时候慎重
最近发现一个Kafka producer异步发送在某些情况会阻塞主线程,后来在排查解决问题过程中发现这可以算是Kafka的一个说明不恰当的地方. 问题说明 在很多场景下我们会使用异步方式来发送Kafk ...
- join为啥会阻塞主线程?
join使用 上篇我们介绍了CountDownLatch,顺便说到了Thread中的join方法! import java.util.concurrent.TimeUnit; /** * @autho ...
- MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)
前面讲了模态对话框和非模态对话框,本节来将一种特殊的对话框--属性页对话框. 属性页对话框的分类 属性页对话框想必大家并不陌生,XP系统中桌面右键点属性,弹出的就是属性页对话框,它通过标签切换各个页面 ...
- VS2010/MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)
前面讲了模态对话框和非模态对话框,本节开始鸡啄米讲一种特殊的对话框--属性页对话框.另外,本套教程所讲大部分对VC++各个版本均可适用或者稍作修改即可,但考虑到终究还是基于VS2010版本的,所以将& ...
- VS2010-MFC(对话框:属性页对话框及相关类的介绍)
转自:http://www.jizhuomi.com/software/164.html 一 属性页对话框的分类 属性页对话框想必大家并不陌生,XP系统中桌面右键点属性,弹出的就是属性页对话框,它通过 ...
- contextmap相当于session之类的 用于设置属性 投放到页面上 contextmap的数据存储在map中
contextmap相当于session之类的 用于设置属性 投放到页面上
- Android之ActionBar、Tabs、Fragment、ViewPager实现标签页切换并缓存页面
感觉 Android 到处都是坑,每个地方都要把人折腾半天. 今天来简单说说 Android之ActionBar.Tabs.Fragment.ViewPager 实现标签页切换并缓存页面 关于他们的介 ...
- 安卓TabLayout+ViewPager实现切页
安卓使用TabLayout+ViewPager+Fragment 实现页面切换,可实现左右滑动切换视图界面和点击切换 可自定义菜单栏是在顶部还是在底部 一.实现效果: 二.实现过程: 2.1 一些重要 ...
- ViewPager之引导页
一.概述 ViewPager是android-support-v4中提供的类,它是一个容器类,常用于页面之间的切换. 本文介绍ViewPager最基础的应用:在多个View之间进行切换,亦即ViewP ...
随机推荐
- android中实现自定义广播
自定义广播分两个步骤:1.发送广播 2.接收广播 一.先看如何接收广播: 我使用的是Android Studio,File->New->Other->Broadcast Receiv ...
- 数据对接—kettle使用之四
上一篇介绍了表输出插件,并通过实例介绍插件的简单使用,如果有这样的需求大家可以参考一下并深入研究插件的其它细节设置.这一篇我们介绍和表输出对应的插件(表输入)的使用. 表输入: 1. 从步骤插入数据: ...
- 使用变量向SQL Server 2008中插入数据
QT通过ODBC连接数据库SQL Server 2008,进行数据插入时遇到的问题: 先把数据存入变量中,如何使用变量进行插入?插入语句该怎么写? QSqlQuery query(db); query ...
- mysql 俩个时间相减后取分钟
CASE WHEN TIMESTAMPDIFF(MINUTE,o.createDate,o.chargingStartDate) != THEN 'APP解锁计费' ELSE '系统自动计费' END ...
- 理解CPU steal time
http://melody-dc.com/2015/11/21/%E7%90%86%E8%A7%A3CPU-steal-time/ http://www.cnblogs.com/yjf512/p/33 ...
- golang之tcp自动重连
操作系统: CentOS 6.9_x64 go语言版本: 1.8.3 问题描述 现有一个tcp客户端程序,需定期从服务器取数据,但由于种种原因(网络不稳定等)需要自动重连. 测试服务器示例代码: /* ...
- Python标准库:内置函数bytes([source[, encoding[, errors]]])
返回一个新的数组对象,这个数组对象不能对数组元素进行改动.每一个元素值范围: 0 <= x < 256.bytes函数与bytearray函数主要差别是bytes函数产生的对象的元素不能改 ...
- Maven 拾遗
01. maven 概要 首先我把 maven 的概念快速的梳理一下,让我们快速地建立起一个比较精确的 maven 应用场景. maven 不是 ant,也不是 make,以前接触的构建工具,需要写一 ...
- JavaWeb应用出现HTTP 500-Unable to compile class for JSP 错误 的解决
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6383192.html 在上一篇博文中,我们把自己本机的web项目部署到了云主机的tomcat上.之后通过浏览器 ...
- UI Automation的两个成熟的框架(QTP 和Selenium)
自己在google code中开源了自己一直以来做的两个自动化的框架,一个是针对QTP的一个是针对Selenium的,显而易见,一个是商业的UI automation工具,一个是开源的自动化工具. 只 ...