您的位置:首页 > 移动开发 > Android开发

另一种方法:当使用ViewPager加载大量View时卡顿严重的简单解决方法

2014-08-26 18:16 751 查看
在做项目的时候,需要自定义一个日历的控件,一开始采用普遍的做法:ViewPager+GridView。很容易想到,在使用的时候非常卡,加载非常慢。查了相关资料,发现基本上都是这种方法:ViewPager嵌套GridView引发的一系列UI卡顿不顺畅的问题,但都未曾从根本上解决问题。后来想到使用异步加载数据的方法,在初始化控件的时候,异步加载需要的日历数据,然后post更新界面,这种方法虽然加快了加载速度,但是滑动还是非常卡,严重影响体验。这时,作者查看了源代码,每次ViewPager在滑动的时候会每次new它的Adapter里面的page并加载数据,这样的方式效率极其低下,基本上没有重用。
既然是Page,一次只显示一页,每页的View都一样,那么何必每次在加载的时候再去new一页page,直接使用已经加载过的Page,只改变Page里面的数据就行了。
基于这种想法,在设计的时候就想着控件继承自AdapterView,通过适配器来适应数据;控件需要3个Page,首次加载3页数据,在Page滑动的时候,判断当前Page是否达到边界,然后交换Page,如图一,达到Page重用的目的。
当向右滑动时,当前Page(Page2)将变得不可见,当Page2完全不可见时,Page1变为当前Page(Page2),Page2变成Page3,而Page2变成page1,以此类推。



代码非常简单,下面贴出一部分关键代码:
 <pre class="java" name="code">                // set up adapter view
private View setupPage(int position, View convert) {
View view = mAdapter.getView(position, convert, this);
LayoutParams params = view.getLayoutParams();
if (null == params)
params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
// attach
if (view == convert) { // reused
if (-1 != indexOfChild(convert))
detachViewFromParent(convert);
attachViewToParent(view, -1, params);
} else
addViewInLayout(view, -1, params, true);
if (null != mItemClickListener) {
view.setOnClickListener(mPageClickListener);
}
return view;
}


然后是配置交换:
private void swapPage(boolean leftToRight) {
if (leftToRight) {
/**
* if should swap the first buffered-page to the last buffered-page
*/
mPosition++;

View temp = mBufferedPages[0];
mBufferedPages[0] = mBufferedPages[1];
mBufferedPages[1] = mBufferedPages[2];
mBufferedPages[2] = temp;
if (mPageCount - 1 != mPosition)
mBufferedPages[2] = setupPage(mPosition + 1, temp);
if (mIsJumpToCurrent) { // if is jumped to current position
mIsJumpToCurrent = false;
mBufferedPages[0] = setupPage(mPosition - 1, mBufferedPages[0]);
}
} else {
mPosition--;
View temp = mBufferedPages[2];
mBufferedPages[2] = mBufferedPages[1];
mBufferedPages[1] = mBufferedPages[0];
mBufferedPages[0] = temp;
if (0 != mPosition)
mBufferedPages[0] = setupPage(mPosition - 1, temp);
if (mIsJumpToCurrent) {
mIsJumpToCurrent = false;
mBufferedPages[2] = setupPage(mPosition + 1, mBufferedPages[2]);
}
}
requestLayout();
if (null != mPageSelectedListener)
mPageSelectedListener.onPageSelected(mBufferedPages[1], mPosition);
}

但是有一个问题,在使用过程中,如果界面上有动画,滑动会出现问题,楼主还在解决中。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息