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

本文介绍了一种改进ViewPager滑动卡顿问题的方法。通过预加载三个页面并重用已加载页面而非每次重新加载,显著提高了滑动流畅度。文章还提供了实现这一优化的关键代码片段。

在做项目的时候,需要自定义一个日历的控件,一开始采用普遍的做法: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);
	}

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

 

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值