3.1 Fragment理論知識及其生命週期,看這一片就夠了

點此進入:從零快速構建APP系列目錄導圖
點此進入:UI編程系列目錄導圖
點此進入:四大組件系列目錄導圖
點此進入:數據網絡和線程系列目錄導圖

一、Fragment 是什麼?

Fragment 是一種可以嵌入在活動當中的 UI 片段,它表示 Activity 中的行爲或用戶界面部分,它能讓程序更加合理和充分地利用大屏幕的空間,因而在平板上應用的非常廣泛。雖然 Fragment 對我們來說應該是個全新的概念,但我相信你學習起來應該毫不費力,因爲它和活動實在是太像了,同樣都能包含佈局,同樣都有自己的生命週期。你甚至可以將碎片理解成一個迷你型的活動,雖然這個迷你型的活動有可能和普通的活動是一樣大的。

我們可以將多個 Fragment 組合在一個 Activity 中來構建多窗格 UI,以及在多個 Activity 中重複使用某個 Fragment 。我們可以將Fragment 視爲 Activity 的模塊化組成部分,而且就像我們前面所說的它具有自己的生命週期,能接收自己的輸入事件,並且我們可以在 Activity 運行時添加或移除 Fragment 。

有一點需要注意,雖然 Fragment 有自己的生命週期,但是 Fragment 必須始終嵌入在 Activity 中才可以使用,其生命週期直接受宿主 Activity 生命週期的影響。例如,當 Activity 暫停時,其中的所有 Fragment 也會暫停;當 Activity 被銷燬時,所有 Fragment 也會被銷燬。 不過,當 Activity 正在運行(處於已恢復生命週期狀態,具體內容你可以參照這篇:1.1 Activity 詳解及其生命週期)時,我們可以獨立操縱每個 Fragment ,比如添加或移除它們。 當我們執行此類 Fragment 事務時,我們也可以將其添加到由 Activity 管理的返回棧(Activity 中的每個返回棧條目都是一條已發生片段事務的記錄)。 返回棧讓用戶可以通過按返回按鈕撤消 Fragment 事務(即“後退”動作)。

而且當我們將 Fragment 作爲 Activity 佈局的一部分添加時,它存在於 Activity 視圖層次結構的某個 ViewGroup 內部,並且 Fragment 會定義其自己的視圖佈局。我們可以通過在 Activity 的佈局文件中聲明片段,將其作爲  元素插入我們的 Activity 佈局中,或者通過將其添加到某個現有 ViewGroup,利用應用代碼進行插入。不過, Fragment 並非必須成爲 Activity 佈局的一部分,我們當然還可以將沒有自己 UI 的 Fragment 用作 Activity 的不可見工作線程,只不過很少這樣使用。

二、設計原理及其設計初衷

Android 在 Android 3.0(API 級別 11)中引入了 Fragment ,主要是爲了給大屏幕(如平板電腦)上更加動態和靈活的 UI 設計提供支持。由於平板電腦的屏幕比手機屏幕大得多,因此可用於組合和交換 UI 組件的空間更大。利用 Fragment 實現此類設計時,我們無需管理對視圖層次結構的複雜更改,通過將 Activity 佈局分成 Fragment ,我們可以在運行時修改 Activity 的外觀,並在由 Activity 管理的返回棧中保留這些更改。

例如,新聞應用可以使用一個 Fragment 在左側顯示文章列表,使用另一個 Fragment 在右側顯示文章:兩個 Fragment 並排顯示在一個 Activity 中,每個 Fragment 都具有自己的一套生命週期回調方法,並各自處理自己的用戶輸入事件。 因此,用戶不需要使用一個 Activity 來選擇文章,然後使用另一個 Activity 來閱讀文章,而是可以在同一個 Activity 內選擇文章並進行閱讀,如下圖所示。

我們應該將每個片段都設計爲可重複使用的模塊化 Activity 組件,也就是說,由於每個 Fragment 都會通過各自的生命週期回調來定義其自己的佈局和行爲,我們可以將一個 Fragment 加入多個 Activity。因此,我們應該採用可複用式設計,避免直接從某個 Fragment 直接操縱另一個 Fragment 。這特別重要,因爲模塊化 Fragment 讓我可以通過更改 Fragment 的組合方式來適應不同的屏幕尺寸。 在設計可同時支持平板電腦和手機的應用時,我們可以在不同的佈局配置中重複使用我的片段,以根據可用的屏幕空間優化用戶體驗。 例如,在手機上,如果不能在同一 Activity 內儲存多個片段,可能必須利用單獨 Fragment 來實現單窗格 UI。

例如:仍然以剛纔說到的新聞應用爲例,在平板電腦尺寸的設備上運行時,該應用可以在 Activity A 中嵌入兩個 Fragment 。 不過,在手機尺寸的屏幕上,由於沒有足以儲存兩個 Fragment 的空間,因此Activity A 只包括用於顯示文章列表的 Fragment ,當用戶選擇文章時,它會啓動Activity B,其中包括用於閱讀文章的第二個 Fragment 。 因此,應用可通過重複使用不同組合的 Fragment 來同時支持平板電腦和手機,正如在上圖中我們看到的那樣。

二、Fragment 的生命週期

1、Fragment 的生命週期回調方法

Fragment 類的代碼與 Activity 非常相似,它包含與 Activity 類似的回調方法,如 onCreate()、onStart()、onPause() 和 onStop()。實際上,如果我們要將現有 Android 應用轉換爲使用 Fragment,只需將代碼從 Activity 的回調方法移入片段相應的回調方法中即可。下面給出的是我們的 Fragment 生命週期圖譜:

可以看到 Fragment 比 Activity 多瞭如下幾個額外的生命週期回調方法:
  • onAttach(Activity):
    當Fragment與Activity發生關聯時調用。
  • onCreateView(LayoutInflater, ViewGroup,Bundle):
    創建該Fragment的視圖。
  • onActivityCreated(Bundle):
    當Activity的onCreate方法返回時調用。
  • onDestoryView():
    與onCreateView相對應,當該Fragment的視圖被移除時調用。
  • onDetach():
    與onAttach相對應,當Fragment與Activity關聯被取消時調用。

注意:除了onCreateView,其他的所有方法如果你重寫了,必須調用父類對於該方法的實現。

通常來講,我們至少應實現以下生命週期方法:
  • onCreate()
    系統會在創建Fragment時調用此方法,我們應該在實現內初始化您想在Fragment暫停或停止後恢復時保留的必需Fragment組件。
  • onCreateView()
    系統會在Fragment首次繪製其用戶界面時調用此方法。 要想爲我們的Fragment繪製 UI,我們從此方法中返回的 View 必須是Fragment佈局的根視圖。如果Fragment未提供 UI,我們可以返回 null。
  • onPause()
    系統將此方法作爲用戶離開Fragment的第一個信號(但並不總是意味着此Fragment會被銷燬)進行調用。 我們通常應該在此方法內確認在當前用戶會話結束後仍然有效的任何更改(因爲用戶可能不會返回)。

大多數應用都應該至少爲每個片段實現這三個方法,但我們還應該使用幾種其他回調方法來處理Fragment生命週期的各個階段。

2、處理 Fragment 的生命週期

管理 Fragment 生命週期與管理 Activity 生命週期很相似,和 Activity 一樣, Fragment 也以三種狀態存在:
- 繼續狀態:
Fragment 在運行中的 Activity 中可見。
- 暫停狀態:
另一個 Activity 位於前臺並具有焦點,但此 Fragment 所在的 Activity 仍然可見(前臺 Activity 部分透明,或未覆蓋整個屏幕)。
- 停止狀態:
Fragment 不可見,宿主 Activity 已停止,或 Fragment 已從 Activity 中移除,但已添加到返回棧。 停止 Fragment 仍然處於活動狀態(系統會保留所有狀態和成員信息),不過它對用戶不再可見,如果 Activity 被終止,它也會被終止。

同樣與 Activity 一樣,假使 Activity 的進程被終止,而我們需要在重建 Activity 時恢復Fragment狀態,我們也可以使用 Bundle 保留Fragment的狀態。我們可以在片段的 onSaveInstanceState() 回調期間保存狀態,並可在 onCreate()、onCreateView() 或 onActivityCreated() 期間恢復狀態。

Activity 生命週期與Fragment生命週期之間的最顯著差異在於它們在其各自返回棧中的存儲方式。 默認情況下,Activity 停止時會被放入由系統管理的 Activity 返回棧(以便用戶通過返回按鈕回退到 Activity。不過,僅當我們在移除Fragment的事務執行期間通過調用 addToBackStack() 顯式請求保存實例時,系統纔會將Fragment放入由宿主 Activity 管理的返回棧。

在其他方面,管理Fragment生命週期與管理 Activity 生命週期非常相似。 因此,管理 Activity 生命週期的做法同樣適用於Fragment。但我們還需要了解 Activity 的生命週期對Fragment生命週期的影響。

注意:如果我們需要在 Fragment 內使用 Context 對象,我們可以調用 getActivity()。但要注意的是,還請僅在 Fragment 附加到 Activity 時調用 getActivity() 。如果 Fragment 尚未附加,或在其生命週期結束期間分離,則 getActivity() 將返回 null。

3、與 Activity 生命週期協調一致

片段所在的 Activity 的生命週期會直接影響 Fragment 的生命週期,具體表現爲:Activity 的每次生命週期回調都會引發每個 Fragment 的類似回調。 例如,當 Activity 收到 onPause() 時,Activity 中的每個 Fragment 也會收到 onPause()。

不過, Fragment 還有幾個額外的生命週期回調,用於處理與 Activity 的唯一交互,以執行構建和銷燬 Fragment UI 等操作。

這些額外的回調方法是:
  • onAttach():
    在片段已與 Activity 關聯時調用 (Activity 傳遞到此方法內)。
  • onCreateView():
    調用它可創建與片段關聯的視圖層次結構。
  • onActivityCreated():
    在 Activity 的 onCreate() 方法已返回時調用。
  • onDestroyView():
    在移除與片段關聯的視圖層次結構時調用。
  • onDetach():
    在取消片段與 Activity 的關聯時調用。

上圖說明了受其宿主 Activity 影響的 Fragment 生命週期流。在該圖中,我們可以看到 Activity 的每個連續狀態如何決定Fragment可以收到的回調方法的。 例如,當 Activity 收到其 onCreate() 回調時,Activity 中的 Fragment 只會收到 onActivityCreated() 回調。

一旦 Activity 達到恢復狀態,我們就可以隨意向 Activity 添加 Fragment 和移除其中的 Fragment 。 因此,只有當 Activity 處於恢復狀態時, Fragment 的生命週期才能獨立變化。不過,當 Activity 離開恢復狀態時, Fragment 會在 Activity 的推動下再次經歷其生命週期。

三、Fragment 的幾個擴展子類

最後我們給出 Fragment 的幾個擴展子類,而不是 Fragment 基類:
- DialogFragment:
顯示浮動對話框。使用此類創建對話框可有效地替代使用 Activity 中的對話框幫助程序方法,因爲我們可以將 Fragment 對話框納入由 Activity 管理的 Fragment返回棧,從而使用戶能夠返回清除的 Fragment。
- ListFragment:
顯示由適配器(如:SimpleCursorAdapter)管理的一系列項目,類似於 ListActivity。它提供了幾種管理列表視圖的方法,如用於處理點擊事件的 onListItemClick() 回調。
- PreferenceFragment:
以列表形式顯示 Preference 對象的層次結構,類似於 PreferenceActivity,這在爲我們的應用創建“設置” Activity 時很有用處。

這裏介紹的這幾個 Fragment 擴展子類和 Fragment 的基類用法基本上是相同的,我們下篇就來開始學習如何使用 Fragment。

點此進入:GitHub開源項目“愛閱”。“愛閱”專注於收集優質的文章、站點、教程,與大家共分享。下面是“愛閱”的效果圖:


聯繫方式:

簡書:WillFlow
CSDN:WillFlow
微信公衆號:WillFlow

微信公衆號:WillFlow

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