天天看點

學習安卓開發[2] - 在Activity中托管Fragment

在上一篇學習安卓開發[1]-程式結構、Activity生命周期及頁面通信中,學習了Activity的一些基礎應用,基于這些知識,可以建構一些簡單的APP了,但這還遠遠不夠,本節會學習如何使用Activity托管Fragment的方式來進行開發

目錄

  • 為什麼需要Fragment
    • 單純使用Activity的局限
    • Fragment介紹
  • 如何使用Fragment
    • 代碼實作
      • 容器視圖和Activity
      • FragmentManager
    • Fragment的生命周期

為什麼需要Fragment呢,這要從Activity的局限說起。在前面使用Activity的過程中已經發現,Activity很容易被銷毀重建,甚至是在裝置旋轉的時候也會被銷毀,為了傳回之前的狀态需要儲存各種界面相關的資訊。

再來假設一種比較常見的場景,一個清單界面+明細界面構成的應用,如果用兩個Activity來實作也可以,但如果使用者在平闆裝置上運作應用,則最好能同時顯示清單和明細記錄,類似網易雲、QQ那樣在螢幕左側約1/3的區域顯示清單,右側剩餘的區域展示詳細資訊,這是使用兩個Activity無法滿足的;另外,檢視能否在使用者想檢視下一條明細時不必回退、再點選進入明細界面,而是采用在螢幕橫向滑動切換到下一條這樣的快捷手勢呢,這也是兩個Activity無法滿足的。

接下來該是Fragment隆重登場的時候了,可以說Fragment就是為了應對UI的靈活需求而生的,Fragment是在API 11中開始引入的,當時Google釋出了第一台平闆裝置。

那麼什麼是Fragment呢,Fragment是一種控制器對象,可以在Activity的托管下進行使用者界面的管理,受其管理的界面可以是整個螢幕區域,也可以是一小部分,Fragment(碎片)就是這個意思。

要讓Activity能夠托管Fragment,則需要activity視圖預留fragment插入其中的位置。一個activity視圖中可以插入過個fragment視圖。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();
	}
}
           

這段代碼的作用是:在資源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的生命周期如下圖所示:

學習安卓開發[2] - 在Activity中托管Fragment

可見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調用的。