學習安卓開發[2] - 在Activity中託管Fragment
在上一篇 學習安卓開發[1]-程式結構、Activity生命週期及頁面通訊 中,學習了Activity的一些基礎應用,基於這些知識,可以構建一些簡單的APP了,但這還遠遠不夠,本節會學習如何使用Activity託管Fragment的方式來進行開發
為什麼需要Fragment
單純使用Activity的侷限
為什麼需要Fragment呢,這要從Activity的侷限說起。在前面使用Activity的過程中已經發現,Activity很容易被銷燬重建,甚至是在裝置旋轉的時候也會被銷燬,為了返回之前的狀態需要儲存各種介面相關的資訊。
再來假設一種比較常見的場景,一個列表介面+明細介面構成的應用,如果用兩個Activity來實現也可以,但如果使用者在平板裝置上執行應用,則最好能同時顯示列表和明細記錄,類似網易雲、QQ那樣在螢幕左側約1/3的區域顯示列表,右側剩餘的區域展示詳細資訊,這是使用兩個Activity無法滿足的;另外,檢視能否在使用者想檢視下一條明細時不必回退、再點選進入明細介面,而是採用在螢幕橫向滑動切換到下一條這樣的快捷手勢呢,這也是兩個Activity無法滿足的。
Fragment介紹
接下來該是Fragment隆重登場的時候了,可以說Fragment就是為了應對UI的靈活需求而生的,Fragment是在API 11中開始引入的,當時Google釋出了第一臺平板裝置。
那麼什麼是Fragment呢,Fragment是一種控制器物件,可以在Activity的託管下進行使用者介面的管理,受其管理的介面可以是整個螢幕區域,也可以是一小部分,Fragment(碎片)就是這個意思。
要讓Activity能夠託管Fragment,則需要activity檢視預留fragment插入其中的位置。一個activity檢視中可以插入過個fragment檢視。Fragment本身沒有在螢幕上顯示檢視的能力,所以它必須放置在Activity的檢視層級中。
如何使用Fragment
程式碼實現
容器檢視和Activity
在檔案activity_fragment.xml中定義容器檢視:
<FrameLayout android:id="@+id/fragment_container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" />
在Activity中定義了一個用於放置Fragment的FrameLayout,這個容器檢視可以託管任意的Fragment。
對應Activity的程式碼在CrimeActivity.java為:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragment_container); if (fragment == null) { fragment = new CrimeFragment(); fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit(); } }
FragmentManager
這段程式碼的作用是:在資源ID為R.id.fragment_container的FrameLayout容器中,找到fragment,然後判斷獲取的fragment是否為空,如果為空則建立新的名為CrimeFragment的Fragment例項,將其新增到FragmentManager所維護的佇列中,並在容器R.id.fragment_container中顯示。
除了這種用程式碼將fragment交給Activity託管的方式,還可以在xml中直接將fragment簽入activity,但為了能夠動態地更換fragment,唯一能採用的便是前面採用的程式碼的方式。
在裝置旋轉或回收記憶體時,Android系統會銷燬Activity,但FragmentManager會將fragment佇列儲存下來。Activity被重建時,新的FragmentManager會首先獲取儲存的佇列(這就是使用了Fragment後,不會有像之前那樣旋轉就會裝置導致狀態丟失的現象的原因)。所以程式碼裡會先判斷fragment是否為null,只有為null的時候才會重新向佇列中新增fragment。
Fragment的生命週期
Fragment的生命週期如下圖所示:

fragment_life_cycle.jpg
可見Fragment的生命週期與Activity的生命週期非常類似,實際上Fragment的許多方法對應著activity的生命週期方法。
Fragment的onCreate方法:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... }
Activity的onCreate方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... }
兩者的區別在於Fragment.OnCreate()是公共方法,而Activity.OnCreate()是受保護方法,Activity的生命週期方法由作業系統呼叫,而Fragment的生命週期方法則是由託管它的Activity呼叫的。