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