博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于ViewPager设置属性页setCurrentItem会阻塞主线程ANR总结
阅读量:5167 次
发布时间:2019-06-13

本文共 2988 字,大约阅读时间需要 9 分钟。

 

关于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的实例化有关,还需要深入研究

 

转载于:https://www.cnblogs.com/xgjblog/p/8341779.html

你可能感兴趣的文章
hadoop17---RPC和Socket的区别
查看>>
使用JMeter代理录制app测试脚本
查看>>
Linq to Object实现分页获取数据
查看>>
mac常用系统命令
查看>>
android上传文件到服务器
查看>>
我回答了90%的面试题,为什么还被拒?
查看>>
Html - Table 表头固定和 tbody 设置 height 在IE不起作用的解决
查看>>
HDU 2262 回溯算法 递归枚举
查看>>
九度0J 1374 所有员工年龄排序
查看>>
微信小程序图片使用示例
查看>>
Ubuntu16.04+cuda8.0rc+opencv3.1.0+caffe+Theano+torch7搭建教程
查看>>
1.开发准备
查看>>
centos su命令
查看>>
CLR:基元类型、引用类型和值类型
查看>>
dubbo序列化hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决...
查看>>
jQuery中的事件绑定的几种方式
查看>>
泥塑课
查看>>
iOS 自定义的对象类型的解档和归档
查看>>
setImageBitmap和setImageResource
查看>>
springMVC4 注解配置实例
查看>>