Android 問題匯總:(一)甲午年 —— 1.4 ViewPager的使用和緩衝機制
1. 實現ViewPager的頁面懶載入;
在某些情況下,例如使用ViewPager查看多張大圖,此時多張圖片不能一次性載入,只有在瀏覽該頁面時才載入(或者預先載入下一頁面)頁面的具體內容。
2. 可控ViewPager快取頁面面的數量。
常見的情況:1.頁面的總數是已知的,或者可以計算出來,每個頁面佔用的資源並不多並且需要經常使用這些頁面。這是可以考慮將其常駐ViewPager而不去銷毀(頻繁的銷毀和重建也會消耗比較多的資源)。2.切換頁面時預設情況下非相鄰的頁面會被銷毀掉(ViewPager預設緩衝或預先載入相鄰的頁面以便快速切換),如果想要保持頁面之前的狀態,如捲軸滾動位置等比較困難;這是可以考慮將之前的頁面緩衝下來而不銷毀掉。
ViewPager的預設載入與緩衝模式
ViewPager和ListView、GridView等的資料載入方式類似,控制項本身都提供了資料載入的適配器介面,程式員只需實現特定的Adapter就可以輕鬆的將資料填充到容器中。
我們來看一個簡單的Demo
1.ViewPager懶載入和緩衝測試類別
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的頁面執行個體化的時候載入資料,預先載入的時候也會執行該方法。
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:當該頁面被選中的時候才載入該頁面的資料,預先載入頁面時不會載入預先載入頁的資料。
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頁面不會被銷毀。
參考資料:
http://ranfeng0610.blog.163.com/blog/static/18570828420137206492642/
http://zilla.blog.51cto.com/3095640/1199366
http://blog.csdn.net/wangjinyu501/article/details/8169924