关于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 ...
随机推荐
- Spring中默认bean名称的生成策略/方式修改
最近公司项目打算模块化,其实一个原因也是为了能够整合公司多个业务的代码,比如一个资源xxx,两个业务中都有对这个资源的管理,虽然是一个资源,但是是完全不同的定义.完全不同的表.不同的处理逻辑.所以打算 ...
- android中使用setOnKeyListener响应输入事件
在界面中添加一个EditText输入框控件,需要在输入时响应输入事件,可以使用setOnKeyListener() 事件: final EditText editText = findViewById ...
- uni - 使用npm
一.使用 1. 在当前根目录初始化package.json npm init -y 2. 安装(自动生成node_modules文件夹) npm i packageName yarn add pack ...
- PetaPoco使用
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connecti ...
- h5可伸缩布局方案
https://github.com/amfe/lib-flexible ib.flexible 移动端自适应方案,相关文章请参考此处 Update[2016年01月13日] 首先,由衷的感谢@完颜( ...
- Unix线程概念、控制原语、属性
线程: 线程基础概念: 线程在Linux中又称轻量级进程.而且它和进程都有PCB(进程控制块).可是差别是进程的虚拟地址空间是独享的,也就是每一个进程都有自己的虚拟地址空间.可是线程的PCB是共享的, ...
- achartengine(Google给android提供的画图工具包)的介绍和使用
AChartEngine(ACE)是Google为Android提供的一个开源绘制工具包.它集成了绘制多种图形的功能:折线图.散点图.气泡图.柱状图.饼图.仪表图等图形. 下载地址:http://do ...
- 栈的实现与操作(C语言实现)
栈的定义 1, 栈是一种特殊的线性表 2,栈仅能在线性表的一端进行操作 3,栈顶(Top): 同意操作的一端 同意操作的一端 4,栈底(Bottom): ,不同意操作的一端 不同意操作 ...
- 算法笔记_221:串的简单处理(Java)
目录 1 问题描述 2 解决方案 1 问题描述 串的处理在实际的开发工作中,对字符串的处理是最常见的编程任务.本题目即是要求程序对用户输入的串进行处理.具体规则如下:1. 把每个单词的首字母变为大 ...
- oracle 批量删除表数据的4种方式
1.情景展示 情景一: 删除PRIMARY_INDEX_TEST表中,MINDEX_ID字段为空的数据 情景二: 删除VIRTUAL_CARD_TEST表中的脏数据 2.解决方案 情景一的解决方案 ...