天天看點

android FragmentpagerAdapter和FragmentStatePagerAdapter的差別

重載實作了幾個必須的函數,是以來自 pageradapter 的函數,我們隻需要實作 getcount(),即可。且,由于 fragmentpageradapter.instantiateitem() 的實作中,調用了一個新增的虛函數 getitem(),是以,我們還至少需要實作一個 getitem()。是以,總體上來說,相對于繼承自 pageradapter,更友善一些。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentpageradapter.java#fragmentpageradapter.getitem%28int%29">getitem()</a>

該類中新增的一個虛函數。函數的目的為生成新的 fragment 對象。重載該函數時需要注意這一點。在需要時,該函數将被 instantiateitem() 所調用。

如果需要向 fragment 對象傳遞相對靜态的資料時,我們一般通過 fragment.setarguments() 來進行,這部分代碼應當放到 getitem()。它們隻會在新生成 fragment 對象時執行一遍。

如果需要在生成 fragment 對象後,将資料集裡面一些動态的資料傳遞給該 fragment,那麼,這部分代碼不适合放到 getitem() 中。因為當資料集發生變化時,往往對應的 fragment 已經生成,如果傳遞資料部分代碼放到了 getitem() 中,這部分代碼将不會被調用。這也是為什麼很多人發現調用 pageradapter.notifydatasetchanged() 後,getitem() 沒有被調用的一個原因。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentpageradapter.java#fragmentpageradapter.instantiateitem%28android.view.viewgroup%2cint%29">instantiateitem()</a>

fragmentpageradapter 會将所有生成的 fragment 對象通過 fragmentmanager 儲存起來備用,以後需要該 fragment 時,都會從 fragmentmanager 讀取,而不會再次調用 getitem() 方法。

如果需要在生成 fragment 對象後,将資料集中的一些資料傳遞給該 fragment,這部分代碼應該放到這個函數的重載裡。在我們繼承的子類中,重載該函數,并調用 fragmentpageradapter.instantiateitem() 取得該函數傳回 fragment 對象,然後,我們該 fragment 對象中對應的方法,将資料傳遞過去,然後傳回該對象。

否則,如果将這部分傳遞資料的代碼放到 getitem()中,在 pageradapter.notifydatasetchanged() 後,這部分資料設定代碼将不會被調用。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentpageradapter.java#fragmentpageradapter.destroyitem%28android.view.viewgroup%2cint%2cjava.lang.object%29">destroyitem()</a>

remove(),隻是 detach(),是以 fragment 還在 fragmentmanager 管理中,fragment 所占用的資源不會被釋放。

不一樣的是,正如其類名中的 'state' 所表明的含義一樣,該 pageradapter 的實作将隻保留目前頁面,當頁面離開視線後,就會被消除,釋放其資源;而在頁面需要顯示時,生成新的頁面(就像 listview 的實作一樣)。這麼實作的好處就是當擁有大量的頁面時,不必在記憶體中占用大量的記憶體。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentstatepageradapter.java#fragmentstatepageradapter.getitem%28int%29">getitem()</a>

一個該類中新增的虛函數。

函數的目的為生成新的 fragment 對象。

fragment.setarguments() 這種隻會在建立 fragment 時執行一次的參數傳遞代碼,可以放在這裡。

getitem() 的。是以這部分代碼應該放到 instantiateitem() 中。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentstatepageradapter.java#fragmentstatepageradapter.instantiateitem%28android.view.viewgroup%2cint%29">instantiateitem()</a>

除非碰到 fragmentmanager 剛好從 savedstate 中恢複了對應的 fragment 的情況外,該函數将會調用 getitem() 函數,生成新的 fragment 對象。新的對象将被 fragmenttransaction.add()。

fragmentstatepageradapter 就是通過這種方式,每次都建立一個新的 fragment,而在不用後就立刻釋放其資源,來達到節省記憶體占用的目的的。

<a target="_blank" href="http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/support/v4/app/fragmentstatepageradapter.java#fragmentstatepageradapter.destroyitem%28android.view.viewgroup%2cint%2cjava.lang.object%29">destroyitem()</a>

繼續閱讀