ViewPager页面懒加载与缓存页面数量可控java
本文目标:
1. 实现ViewPager的页面懒加载;
在某些状况下,例如使用ViewPager查看多张大图,此时多张图片不能一次性载入,只有在浏览该页面时才载入(或者预先载入下一页面)页面的具体内容。
2. 可控ViewPager缓存页面的数量。
常见的状况:1.页面的总数是已知的,或者能够计算出来,每一个页面占用的资源并很少而且须要常用这些页面。这是能够考虑将其常驻ViewPager而不去销毁(频繁的销毁和重建也会消耗比较多的资源)。2.切换页面时默认状况下非相邻的页面会被销毁掉(ViewPager默认缓存或预加载相邻的页面以便快速切换),若是想要保持页面以前的状态,如滚动条滚动位置等比较困难;这是能够考虑将以前的页面缓存下来而不销毁掉。
ViewPager的默认加载与缓存模式
ViewPager和ListView、GridView等的数据加载方式相似,控件自己都提供了数据加载的适配器接口,程序员只需实现特定的Adapter就能够轻松的将数据填充到容器中。
咱们来看一个简单的Demo
1.ViewPager懒加载和缓存测试类
android
package com.example.viewpagertest; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class MainActivity extends Activity { private static final String TAG = "com.example.viewpagertest.MainActivity"; private MyViewPager viewPager; private List<View> pagers = new ArrayList<View>(); /** ViewPager缓存页面数目;当前页面的相邻N各页面都会被缓存 */ private int cachePagers = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getViews(); setContentView(viewPager); setListener(); setAdapter(); } private void getViews() { viewPager = new MyViewPager(this); for (int i = 0; i < 5; i++) { TextView textView = new TextView(this); pagers.add(textView); viewPager.onDisplay(i);//测试1 } viewPager.setOffscreenPageLimit(cachePagers);// 设置缓存页面,当前页面的相邻N各页面都会被缓存 } private void setAdapter() { viewPager.setAdapter(pagerAdapter); } private void setListener() { viewPager.setOnPageChangeListener(pageChangeListener); } /** * 页面数据适配器 */ private PagerAdapter pagerAdapter = new PagerAdapter() { @Override public void destroyItem(View container, int position, Object object) { Log.i(TAG, "destroyItem:" + position); ((ViewGroup) container).removeView((View) object); } @Override public void destroyItem(ViewGroup container, int position, Object object) { Log.i(TAG, "destroyItem:" + position); container.removeView((View) object); } @Override public Object instantiateItem(View container, int position) { Log.i(TAG, "instantiateItem:" + position); try { ((ViewPager) container).addView(pagers.get(position)); // ((MyViewPager) container).onDisplay(position);//测试2 } catch (Exception e) { Log.e(TAG, e.getMessage()); } return pagers.get(position); } @Override public Object instantiateItem(ViewGroup container, int position) { Log.i(TAG, "instantiateItem:" + position); try { ((ViewPager) container).addView(pagers.get(position)); // ((MyViewPager) container).onDisplay(position);//测试2 } catch (Exception e) { Log.e(TAG, e.getMessage()); } return pagers.get(position); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public int getCount() { return pagers.size(); } }; /** * 页面滚动监听器 */ private OnPageChangeListener pageChangeListener = new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { Log.i(TAG, "onPageSelected:" + arg0); // viewPager.onDisplay(arg0);//测试3 } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }; /** * @Title setPageData * @Description 加载页面数据 * @param position */ private void setPageData(int position) { TextView textView = (TextView) pagers.get(position); textView.setText("pager" + position); Log.i(TAG, "setPageData position:" + position); } class MyViewPager extends ViewPager implements IPagerDisplay { public MyViewPager(Context context) { super(context); } public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onDisplay(int position) { setPageData(position); } } }
2.ViewPager数据展现回调接口
程序员
/** * @Title IPagerDisplay.java * @Package com.example.viewpagertest * @Description ViewPager数据展现回调 * @author ze.chen * @date 2013-5-13 下午2:25:38 * @version V1.0 */ package com.example.viewpagertest; /** * @ClassName IPagerDisplay * @Description ViewPager懒加载展接口;能够在PagerAdapter的instantiateItem时候调用, * 亦能够在OnPageChangeListener的onPageSelected时候调用 * ,两处的区别在于,instantiateItem方法ViewPager会自动缓冲 * (浏览pager1时将pager2的数据加载好), * 而onPageSelected则不会自动缓冲(浏览pager2时才加载pager2的数据) * @author ze.chen * @date 2013-5-13 下午2:25:38 * */ public interface IPagerDisplay { void onDisplay(int position); }
使ViewPager支持懒加载
在以上代码段中,分别注释了:测试1;测试2;测试3。
测试1:在加载ViewPager以前,初始化全部的页面和数据
缓存
viewPager = new MyViewPager(this); for (int i = 0; i < 5; i++) { TextView textView = new TextView(this); pagers.add(textView); viewPager.onDisplay(i);//测试1 }
对于测试2和测试3,只将控件添加到pagers列表中,数据不马上加载
测试2:在ViewPager的页面实例化的时候加载数据,预加载的时候也会执行该方法。
app
public Object instantiateItem(View container, int position) { Log.i(TAG, "instantiateItem:" + position); try { ((ViewPager) container).addView(pagers.get(position)); ((MyViewPager) container).onDisplay(position);//测试2 } catch (Exception e) { Log.e(TAG, e.getMessage()); } return pagers.get(position); }
测试3:当该页面被选中的时候才加载该页面的数据,预加载页面时不会加载预加载页的数据。
ide
private OnPageChangeListener pageChangeListener = new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { Log.i(TAG, "onPageSelected:" + arg0); viewPager.onDisplay(arg0);//测试3 } ……
修改ViewPager的缓存页面数量
测试
viewPager.setOffscreenPageLimit(int numbers);
viewpager当前页面两侧缓存/预加载的页面数目。当页面切换时,当前页面相邻两侧的numbers页面不会被销毁。
this