理解PagerAdapter的instantiateItem()方法


 

在為ViewPager設置Adapter時肯定會用到PagerAdapter,Google Android文檔對該類的定義如下:

Base class providing the adapter to populate pages inside of a ViewPager. You will most likely want to use a more specific implementation of this, such as FragmentPagerAdapter or FragmentStatePagerAdapter.

When you implement a PagerAdapter, you must override the following methods at minimum:

  • instantiateItem(ViewGroup, int)
  • destroyItem(ViewGroup, int, Object)
  • getCount()
  • isViewFromObject(View, Object)

上述四個方法是必須得到重載的,其他的不管,我們今天只看instantiateItem (View container, int position),對於該方法的說明如下:

Parameters
container The containing View in which the page will be shown.
position The page position to be instantiated.
Returns
  • Returns an Object representing the new page. This does not need to be a View, but can be some other container of the page.

我的理解是一個Page在切換完成后會調用該方法去加載下一個即將展示的Page,至於是哪個Page取決於切換動作,比如Page1切換到Page2,切換完成后會調用該方法去加載Page3。空說無憑,試着重寫該方法打個log出來看看,下面是我重載的instantiateItem()方法:

     @Override
        public Object instantiateItem(View arg0, int arg1) {
            ViewGroup v = (ViewGroup) mListViews.get(arg1).getParent();
            if (v != null) {
                v.removeView(mListViews.get(arg1));
            } else {
                Log.i("Allen", String.valueOf(arg1 + 1));
            }
            ((ViewPager) arg0).addView(mListViews.get(arg1), 0);
            return mListViews.get(arg1);
        }

問題一:是否是真的為即將展示頁做操作?

第一句獲取父組件后面會說到用處,mListViews定義如下:

mViews = new ArrayList<View>();
mViews.add(viewOne);
mViews.add(viewTwo);
mViews.add(viewThree);
mViews.add(viewFour);

當我從page1->page2->page3->page4->page3->page2->page1,日志如下:

11-07 00:14:38.803: I/Allen(31124): 1
11-07 00:14:38.803: I/Allen(31124): 2
11-07 00:14:56.853: I/Allen(31124): 3
11-07 00:15:00.998: I/Allen(31124): 4
11-07 00:15:05.498: I/Allen(31124): 2
11-07 00:15:07.208: I/Allen(31124): 1

除了第一次進入page1會多打出“1”,其余的切換page操作都會打出"下一次即將顯示的頁",從page3到page4不會有日志記錄,因為沒有即將出現在page4之后的頁。

因此問題一的答案是肯定的。

問題二:為什么要獲取父組件?

這個操作后來檢查發現是不必要的,出現這個操作的原因是我在設置Adapter之前做了如下操作:

mPager = (ViewPager) findViewById(R.id.guide_pager);
mPager.addView(viewOne);
mPager.addView(viewTwo);
mPager.addView(viewThree);
mPager.addView(viewFour);

如果不獲取父組件並對子view進行remove操作,會報如下錯誤

java.lang.IllegalStateException The specified child already has a parent. You must call removeView() on the child's parent first.  

這個操作打出的日志也是不同的,同樣是page1->page2->page3->page4->page3->page2->page1,日志如下:

11-07 00:28:11.158: I/Allen(1688): 2
11-07 00:28:13.963: I/Allen(1688): 1

這是因為在第一次page1到page4的切換過程中,4個page早已被加到pager中,所以第一次進入page1打印的“1”和“2”,page2的“3”以及page3的“4”是不會打印出來的,只有page3的“2”和page2的“1”。由此我猜想pager對page做了窗口處理,窗口長度大小為3,即始終保存當前page,切換前page和即將切換page。

讀者完全不必采用筆者提前為Pager添加addView的處理,如果這樣處理就要及時從父組件中移除view


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM