1. 程式人生 > >實現ViewPager懶載入的三種方法

實現ViewPager懶載入的三種方法

在專案中ViewPager和Fragment介面框架已經是處處可見,但是在使用中,我們肯定不希望使用者在當前頁面時就在前後頁面的資料,加入資料量很大,而使用者又不願意左右滑動瀏覽,那麼這時候ViewPager中本來充滿善意的預載入就有點令人不爽了。我們能做的就是遮蔽掉ViewPager的預載入機制。雖然ViewPager中提供的有

setOffscreenPageLimit()來控制其預載入的數目,但是當設定為0後我們發現其根本沒效果,這個的最小值就是1,也就是你只能最少前後各預載入一頁。那麼,這時候就得另覓方法了。

以下三種方法是我在學習和專案中嘗試過的,需求實現了,但各有千秋,可結合不同場景使用。因為打算慢慢養成寫部落格的習慣,就總結在此,也希望對他人有所借鑑。

方法一 

在Fragment可見時請求資料。此方案仍預載入了前後的頁面,但是沒有請求資料,只有進入到當前Framgent時才請求資料。

優點:實現了資料的懶載入

缺點:一次仍是三個Framgment物件,不是完全意義的懶載入

  1. publicclassFragmentSampleextendsFragment{

  2. ...

  3. @Override

  4. publicvoid setUserVisibleHint(boolean isVisibleToUser){

  5. super.setUserVisibleHint(isVisibleToUser);

  6. if(isVisibleToUser){

  7.            requestData

    (); // 在此請求資料

  8. }

  9. }

  10. ...

  11. }

方法二

直接修改ViewPager原始碼。通過檢視ViewPager原始碼可知,控制其預載入的是一個常量

DEFAULT_OFFSCREEN_PAGES,其預設值為1,表示當前頁面前後各預載入一個頁面,在這裡我們直接將其設定為0即可,即去掉預載入。但是,這樣有一個問題,那就是在使用其他控制元件時需要傳入ViewPager時,這個就不能用了。

優點:完全遮蔽掉了預載入

缺點:應用太受限制,比如使用ViewPagerIndicator時需要傳入ViewPager物件,這時傻眼了。

  1. // 注意,這是直接拷貝的ViewPager的原始碼,只修改了註釋處的程式碼
  2. public class LazyViewPager extends ViewGroup {
  3. private static final String TAG = "LazyViewPager";
  4. private static final boolean DEBUG = false;
  5. private static final boolean USE_CACHE = false;
  6. // 預設為1,即前後各預載入一個頁面,設定為0去掉預載入
  7. private static final int DEFAULT_OFFSCREEN_PAGES = 0;
  8. private static final int MAX_SETTLE_DURATION = 600; // ms
  9. static class ItemInfo {
  10. Object object;
  11. int position;
  12. boolean scrolling;
  13. }
  14. private static final Comparator<ItemInfo> COMPARATOR = new Comparator<ItemInfo>() {
  15. @Override
  16. public int compare(ItemInfo lhs, ItemInfo rhs) {
  17. return lhs.position - rhs.position;
  18. }
  19. };
  20. ............
  21. }

方法三

直接繼承ViewPager,結合PagerAdapter實現懶載入。該方案是我用到的最完善的方法,完全的懶載入,每次只會建立一個Fragment物件。

優點:完全遮蔽預載入

缺點:稍微複雜,但是人家已經造好的輪子,直接用吧,很簡潔

這個庫就4個類,作者通過繼承ViewPager(保證其普適性)、自定義ViewPagerAdapter和 LazyFragmentPagerAdapter以及設定懶載入的標記介面,很好的實現了懶載入。感謝作者。

在此貼出關鍵程式碼,有興趣的同學可以學習下。

LazyViewPager:

  1. publicclassLazyViewPagerextendsViewPager{
  2. privatestaticfinalfloat DEFAULT_OFFSET =0.5f;
  3. privateLazyPagerAdapter mLazyPagerAdapter;
  4. privatefloat mInitLazyItemOffset = DEFAULT_OFFSET;
  5. publicLazyViewPager(Context context){
  6. super(context);
  7. }
  8. publicLazyViewPager(Context context,AttributeSet attrs){
  9. super(context, attrs);
  10. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LazyViewPager);
  11. setInitLazyItemOffset(a.getFloat(R.styleable.LazyViewPager_init_lazy_item_offset, DEFAULT_OFFSET));
  12. a.recycle();
  13. }
  14. /**
  15. * change the initLazyItemOffset
  16. * @param initLazyItemOffset set mInitLazyItemOffset if {@code 0 < initLazyItemOffset <= 1}
  17. */
  18. publicvoid setInitLazyItemOffset(float initLazyItemOffset){
  19. if(initLazyItemOffset >0&& initLazyItemOffset <=1){
  20. mInitLazyItemOffset = initLazyItemOffset;
  21. }
  22. }
  23. @Override
  24. publicvoid setAdapter(PagerAdapter adapter){
  25. super.setAdapter(adapter);
  26. mLazyPagerAdapter = adapter !=null&& adapter instanceofLazyPagerAdapter?(LazyPagerAdapter) adapter :null;
  27. }
  28. @Override
  29. protectedvoid onPageScrolled(int position,float offset,int offsetPixels){
  30. if(mLazyPagerAdapter !=null){
  31. if(getCurrentItem()== position){
  32. int lazyPosition = position +1;
  33. if(offset >= mInitLazyItemOffset && mLazyPagerAdapter.isLazyItem(lazyPosition)){
  34. mLazyPagerAdapter.startUpdate(this);
  35. mLazyPagerAdapter.addLazyItem(this, lazyPosition);
  36. mLazyPagerAdapter.finishUpdate(this);
  37. }
  38. }elseif(getCurrentItem()> position){
  39. int lazyPosition = position;
  40. if(1- offset >= mInitLazyItemOffset && mLazyPagerAdapter.isLazyItem(lazyPosition)){
  41. mLazyPagerAdapter.startUpdate(this);
  42. mLazyPagerAdapter.addLazyItem(this, lazyPosition);
  43. mLazyPagerAdapter.finishUpdate(this);
  44. }
  45. }
  46. }
  47. super.onPageScrolled(position, offset, offsetPixels);
  48. }
  49. }

  1. publicabstractclassLazyFragmentPagerAdapterextendsLazyPagerAdapter<Fragment>{
  2. privatestaticfinalString TAG ="LazyFragmentPagerAdapter";
  3. privatestaticfinalboolean DEBUG =false;
  4. privatefinalFragmentManager mFragmentManager;
  5. privateFragmentTransaction mCurTransaction =null;
  6. publicLazyFragmentPagerAdapter(FragmentManager fm){
  7. mFragmentManager = fm;
  8. }
  9. @Override
  10. publicvoid startUpdate(ViewGroup container){
  11. }
  12. @Override
  13. publicObject instantiateItem(ViewGroup container,int position){
  14. if(mCurTransaction ==null){
  15. mCurTransaction = mFragmentManager.beginTransaction();
  16. 相關推薦

    實現ViewPager載入方法

    在專案中ViewPager和Fragment介面框架已經是處處可見,但是在使用中,我們肯定不希望使用者在當前頁面時就在前後頁面的資料,加入資料量很大,而使用者又不願意左右滑動瀏覽,那麼這時候ViewPager中本來充滿善意的預載入就有點令人不爽了。我們能做的就是遮蔽掉View

    Python實現下載檔案的方法

    下面來看看三種方法是如何來下載zip檔案的:方法一: import urllib print "downloading with urllib" url = 'http://www.jb51.net//test/demo.zip' urllib.urlretrieve(url, "demo.zip")

    vue webpack 載入方式

    const router = new Router({     routes: [          {                path:

    vue+element ui專案總結點(一)select、Cascader級聯選擇器、encodeURI、decodeURI轉碼解碼、一級mockjs用法、路由載入方式

    不多說上程式碼: <template> <div class="hello"> <h1>{{ msg }}</h1> <p>Element UI簡單Cascader級聯選擇器使用</p> <

    Java實現ping功能的方法

    檢測裝置的執行狀態,有的是使用ping的方式來檢測的。所以需要使用java來實現ping功能。 為了使用java來實現ping的功能,有人推薦使用java的 Runtime.exec()方法來直接呼叫系統的Ping命令,也有人完成了純Java實現Ping的程式,使用的是Jav

    Nginx實現404頁面的方法

    一個網站專案,肯定是避免不了404頁面的,通常使用Nginx作為Web伺服器時,有以下集中配置方式: 第一種:Nginx自己的錯誤頁面 Nginx訪問一個靜態的html 頁面,當這個頁面沒有的時候,

    java實現動態代理的方法

    緒論:以下三種java實現動態代理的的方式,分別為基於jdk的,基於cglib的和基於javassist的,其中需要注意的兩點 一:基於jdk實現的動態代理需要實現父類,而其他兩種不需要 二:其中基於cglib的需要額外的jar包依賴,pom的依賴如下 <!-- https://m

    Android移動開發 實現按鈕機制的方法

           Android開發中有三種主要的方式用於設定View的點選事件,1、建立內部類;2、主類中實現OnClickListener介面;3、使用匿名內部類。這三種方式都用到了OnClickListener介面,只是不同形式而已。其中OnClickListener是監

    MyBatis實現模糊查詢的方法

    模糊查詢也是資料庫SQL中使用頻率很高的SQL語句,使用MyBatis來進行更加靈活的模糊查詢。 直接傳參法 直接傳參法,就是將要查詢的關鍵字keyword,在程式碼中拼接好要查詢的格式,如%keyword%,然後直接作為引數傳入mapper.xml的對映檔案中。在查詢前

    Android實現資料持久化的方法

    考慮下面幾種情況: 使用者對應用的亮度、音量、字型顏色等進行了配置; 使用者在遊戲過程中打出了新的記錄; 使用者使用應用下載了一些圖片、音樂等大檔案; 在使用者使用應用時,上述情況經常會出現,此時就要求應用具有儲存這些資料並在以後讀取的能力,也就是所謂的

    Python實現矩陣相乘的方法

    問題描述 分別實現矩陣相乘的3種演算法,比較三種演算法在矩陣大小分別為 22∗22 2^2*2^2, 23∗23 2^3*2^3, 24∗24 2^4*2^4, 25∗25 2^5*2^5,

    實現HTTP伺服器的方法

    1、使用socket簡單實現http協議: import java.io.*;  import java.net.*;  /**  * MyHttpServer 實現一個簡單的HTTP伺服器端,可以獲取使用者提交的內容  * 並給使用者一個response  * 因為

    Java實現定時排程的方法

    1、Timer Timer myTimer = new Timer();           myTimer.schedule(new Worker(), 1000);//1秒後執行   //      2012-02-28 09:58:00執行           myT

    java實現定時任務的方法

    /** * 普通thread * 這是最常見的,建立一個thread,然後讓它在while迴圈裡一直執行著, * 通過sleep方法來達到定時任務的效果。這樣可以快速簡單的實現,程式碼如下: * @author GT * */ public class Task

    介面學習,實現多型的方法何時使用

    介面是一種規範。 只要一個類繼承了一個介面,這個類就必須實現這個介面中所有的成員 為了多型。 介面不能被例項化。 也就是說,介面不能new(不能建立物件) 介面中的成員不能加“訪問修飾符”,介面中的成員訪問修飾符為public,不能修改。 (預設為publi

    實現區域性重新整理的方法

    1、  AJAX主要應用到的是區域性重新整理。也就是當頁面上的摸一個標籤內容需要重新整理,為了不引起整個頁面的回發,通常利用AJAX來解決。 2、獲取其他網頁的內容。當本頁內容基於其他網站時(例如天氣預報),通常也使用AJAX+正則表示式的方法,從外網截獲自己需要的內容。

    C#實現字元替換的方法

    最簡單粗暴的方法 C#封裝了Replace的方法,這個方法及其它的引數是這樣的。 string Replace(替換的目標,替換的字串) 返回值是替換後的字串 string str = "11xx1111x"; Console.Wri

    jQuery實現圖片載入的兩方法記錄

    記錄一 整體思路: 設定個data-original(自定義一個屬性)來存放真實地址 當滾動頁面時,檢查所有的img標籤,看是否出現在視野中,如果已經出現在了視野中,那繼續再進行判斷,看其是否已經被載入過了,如果還沒有被載入過,那就進行載入。 程式碼: laz

    C#實現發送郵件的方法

    thumbnail catch plugins () listbox 幫助 哈希 .text sbo 本文實例講述了C#實現發送郵件的三種方法。分享給大家供大家參考。具體方法分析如下: 一、問題: 最近公司由於一個R&I;項目的需要,用戶要求在購買產品或出貨等

    QComboBox實現復選功能(方法:嵌套QListWidget, 設置QStandardItemModel, 設置Delegate)

    編輯 int() move bsp 下一個 tab url 進行 問題 今天介紹一下一個小東西 — 如何讓QComboBox實現復選功能? 需求: 下拉列表有復選功能 不可編輯 顯示所有選中項 關於QComboBox的復選功能有幾種