ViewPager頁面懶加載與緩存頁面數量可控

ViewPager頁面懶加載與緩存頁面數量可控


本文目標:
1.    實現ViewPager的頁面懶加載;
在某些情況下,例如使用ViewPager查看多張大圖,此時多張圖片不能一次性載入,只有在瀏覽該頁面時才載入(或者預先載入下一頁面)頁面的具體內容。
2.    可控ViewPager緩存頁面的數量。
常見的情況:1.頁面的總數是已知的,或者可以計算出來,每個頁面佔用的資源並不多並且需要經常使用這些頁面。這是可以考慮將其常駐ViewPager而不去銷燬(頻繁的銷燬和重建也會消耗比較多的資源)。2.切換頁面時默認情況下非相鄰的頁面會被銷燬掉(ViewPager默認緩存或預加載相鄰的頁面以便快速切換),如果想要保持頁面之前的狀態,如滾動條滾動位置等比較困難;這是可以考慮將之前的頁面緩存下來而不銷燬掉。
ViewPager的默認加載與緩存模式
ViewPager和ListView、GridView等的數據加載方式類似,控件本身都提供了數據加載的適配器接口,程序員只需實現特定的Adapter就可以輕鬆的將數據填充到容器中。
我們來看一個簡單的Demo
1.ViewPager懶加載和緩存測試類

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的頁面實例化的時候加載數據,預加載的時候也會執行該方法。

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頁面不會被銷燬。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章