關於ViewPager的數據更新問題小結

       今天工作中遇到了這個糾結的問題,在ViewPager中調用PagerAdapter.notifyDataSetChanged()方法,好像沒有任何作用,相應的View也沒有更新數據,根據官方API是這樣解釋的:大概是說明Adapter會自動管轄ViewPager每一頁(Item)的狀態,而notifyDataSetChanged()是用在當Vie Pager要新增一頁、刪除一頁或改變各個頁面的排列的時候。所以ViewPager Adapter的notifyDataSetChanged自然就不適用於只更新View Pager裏面某個View的內容的需求。對此查閱後終於得到了一個相對穩定的解決方案,Mark一下。

 

一、一種簡單的解決方案

   

       這種方案我相信只要是對ViewPager數據更新問題有研究的都會了解,即覆蓋PagerAdapter中的getItemPosition()方法,這種方案雖然簡單,但是因爲這種方法是讓每次呼叫PagerAdapter時,都會遍歷childView,通過getItemPosition()方法返回Item位置失去的參數,這樣PagerAdapter誤認爲Item失去位置,因而重新建立所有childView,這樣做來,開銷過大,而且由於佔用了getItemPosition()方法,也不適用於複雜的View界面,只適合TextView,EditText等簡單的View。

 

覆蓋代碼:

         public int getItemPosition(Object object){   
                return POSITION_NONE;
         }

 

二、PagerAdapter的工作機制

 

        這裏所說的工作機制,嚴格意義上講就是PagerAdapter的執行順序,也是Leo8573通過調試自己理解的。

        PagerAdapter作爲ViewPager的適配器,無論ViewPager有多少頁,PagerAdapter在初始化時也只初始化開始的2個View,即調用2次instantiateItem方法。而接下來每當ViewPager滑動時,PagerAdapter都會調用destroyItem方法將距離該頁2個步幅以上的那個View銷燬,以此保證PagerAdapter最多隻管轄3個View,且當前View是3箇中的中間一個,如果當前View缺少兩邊的View,那麼就instantiateItem,如裏有超過2個步幅的就destroyItem。

 

簡易圖示:
                       *
       ------+---+---+---+------
         ... 0 | 1 | 2 | 3 | 4 ...
       ------+---+---+---+------

     當前View爲2號View,所以PagerAdapter管轄1、2、3三個View,接下來向左滑動-->

                       *
       ------+---+---+---+------
         ... 1 | 2 | 3 | 4 | 5 ...
       ------+---+---+---+------

     滑動後,當前View變爲3號View,PagerAdapter會destroyItem 0號View,instantiateItem 5號View,所以PagerAdapter管轄2、3、4三個View

 

大概就是這樣,各位領會精神吧,Leo8573文字表達能力還是有點差。

 

三、較通用的解決方案

 

       所謂通用的方案,即對於任何ViewPager中的View都可以進行數據更新,具體的方法是每當Adapter調用instantiateItem時,運用View.setTag方法將該View標識。當需要更新這個View的數據時,通過調用ViewPager.findViewWithTag方法找到相應的View,然後更新View中的數據。不能空說不練,最後給上關鍵代碼,領會精神。

 

代碼示例:

@Overridepublic Object instantiateItem(ViewGroup container, int position) {
    View view = null;
    view = mInflater.inflate(R.layout.record_list_layout, null);
    TextView tvRecord = (TextView) view.findViewById(R.id.tv_record);
    String key = "tvRecord" + position;   
// 關鍵點,針對要更新的View來設定Tag,主要是在後續使用ViewPager.findViewWithTag()時,可以找到要更新的View
    tvRecord.setTag(key);
    container.addView(view)
    return view;}  

// 在後續的應用當中,如果要開始更新View Pager當中某個View的內容時,需要進行下列動作
     TextView tvRecord = myViewPager.findViewWithTag("tvRecord1"); 
// 假設要更新第2頁的TextView 
// 進行內容更新
     if (tvRecord != null ) {    tvRecord.setText("update");
    } /* end of if */
}

上是自己查閱信息後的小體會,不對的地方請各位朋友指正,Leo8573鞠躬下臺。

 

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