Fragment隨筆

berber78發表於2015-05-25

前言:本文基於相關文章加以整理、彙編。

FragmentActivity是為彌補早期 Activity沒有 Fragment功能而出現;

====================

在使用ViewPager與Fragment的時候,ViewPager會自動快取1頁內的資料,如下圖:

這裡寫圖片描述

當我們當前處在頁面2的時候,頁面1和頁面3的View實際上已經建立好了,所以在我們拖動的時候是可以看見他們的介面的。但是當我們的頁面處在1的時候,頁面3實際上就已經銷燬了。直到跳轉到頁面2的時候,頁面3才會建立View。這時,如果頁面3中有需要耗時的事件,比如網路訪問。那麼,在我們進行 1–>2 的操作的時候,就會不斷的出現頁面3載入的對話方塊(如果有的話)。而且如果快速的 1–>2–>3的切換,3中的內容很可能還沒載入出來。新增程式碼pager.setOffscreenPageLimit(2);就可以讓ViewPager多快取一個頁面,這樣上面的問題就得到了解決。

======================

坑1:一般情況都會想當然的以為程式被殺掉之後,Fragment也會被回收

其實,Fragment有自己的生命週期,有自己的管理器(FragmentManager),也即:包含Fragment的程式被幹掉,Fragment不一定會被回收,而是由FragmentManager來決定生死。

Q:如何驗證上面的說法?
A:如果是一般正常的流程“開啟-關閉”軟體,Fragment的確被回收了。但是如果使用“騰訊手機管家”之類的記憶體清理工具,清理記憶體(實際上是殺死程式),會發現Fragment沒有被回收,一直快取著。驗證方法如下:快取Fragment的Tag到本地資料庫(可以是xml/sqlite等),然後用FragmentManager.findFragmentByTag(…)是否為Null來驗證Framgent是否被回收了。

有個奇怪的現狀是:在上面藍色的情況發生後,Framgent和包含他的Activity的生命週期順序都亂套了,原本是:
Activity.onCreate–>Fragment.onCreate–>Fragment.onCreateView
變成:
Fragment.onCreate–>Activity.onCreate–>Fragment.onCreateView
猜測是因為直接用的Frament快取,其onCreate先於父Activity.onCreate執行了。

======================

配置(Configuration )改變是Android應用生命週期的一部分,如果發生了該事件(螢幕從橫屏換行為豎屏),就會導致Activity被銷燬然後重新建立。就算您在配置檔案中設定Activity為豎屏顯示的 也無法避免,應為Android應用配置改變的情況有很多種。

如果發生了這種情況,Fragment也會被銷燬然後重新建立。如果您是在執行時(在Java程式碼中新增Fragment到Activity,不是在Activity的佈局檔案中宣告的)建立的,則需要額外小心:

當Activity第一次建立的時候,您需要新增Fragment;當由於配置條件改變導致Activity被重新建立則無需再次新增Fragment(系統會自動新增Fragment)。

所以問題來了,您如何知道何時應該在onCreate函式中新增Fragment呢?

判斷的方法就是檢查 savedInstanceState 引數,如果該引數為null說明是第一次建立,需要新增Fragment;如果不是null則無需新增。程式碼如下:

public class MyActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstnaceState);
        // Only add fragment if this is the initial Activity creation
        if (savedInstanceState == null) {
            FragmentManager fragmentManager =
                     getFragmentManager()
            FragmentTransaction fragmentTransaction =
                     fragmentManager.beginTransaction();
            ExampleFragment fragment = new ExampleFragment();
            fragmentTransaction.add(R.id.fragment_container, fragment);
            fragmentTransaction.commit();
        } else {
            // Don't add the fragment!
            // (and use savedInstanceState to restore Activity state)
        }
    }
}

如果您沒有按照上面的方式新增Fragment,則您的應用可能會出現一種奇怪的現象,同樣的Fragment新增了多次。 關於Fragment使用的更多文件請參考 開發者指南 。