Fragment必須內嵌到activity中,它不能單獨使用,並且它的生命周期受到activity生命周期的制約——當activity暫停時,所有的fragment暫停,當activity停止時,所有的fragment停止。只有當activity處於運行態(resumed in lifecycle state)時,才可以單獨操作各個fragment,比如添加或刪除。在fragment事件中,activity管理着一個fragment返回棧。
在activity的layout中,fragment存在於activity的一個ViewGroup內。並且fragment定義了自己的view布局。有兩種方式添加fragment布局——一是在activity layout中使用<fragment>標簽。或者在代碼中添加到一個ViewGroup中。當然,fragment也可以以沒有UI的方式存在。
Creating a Fragment
創建一個Fragment的方法,同創建activity一樣,需要創建一個繼承自Fragment類或其子類的一個類,並實現onCreate(),onStart()等必要的回調方法。
Fragment生命周期和其對應的生命周期回調方法以及它和activity生命周期的關系圖如下:
同activity一樣,fragment也有三種存活狀態。
Resumed fragment在activity運行時處於可見位置
Paused 另一個activity處於前台獲得焦點,但fragment所在的activity仍是可見的,未被完全覆蓋。
Stopped fragment完全不可見。出現這種情況有兩種可能,一是activity處於停止狀態,二是fragment從activity中刪除掉加入到返回棧中。一個停止態的fragment仍處於激活態(它的所有狀態和成員信息由系統保留)。
同activity一樣,當activity進程被系統殺死,重新創建fragment后,我們想恢復之前保存的狀態,做法是在onSaveInstanceState()中保存相關的數據,而在onCreate(),onCreateView()或者onActivityCreated()中恢復保存的數據。
當activity停止時,它被自動保存在一個由系統管理的返回棧中,用戶可以點擊返回按鈕回到這個activity。然而,fragment被保存在一個由activity管理的返回棧中,當去除fragment時,我們必須顯式的調用addToBackStack()才能把它保存在返回棧中。
fragment的生命周期受到activity生命周期的直接影響。比如,當activity接收onPause()時,該activity中的每個fragment都會接收onPause()。需要指出的是fragment中新有的幾個回調函數。
onAttach() fragment被綁定到activity時調用。
onCreateView() 創建fragment布局視圖時調用。
onActivityCreated() 當activity的onCreate()方法返回時調用。
onDestroyView() fragment視圖刪除時調用。
onDetach() fragment從activity中解除綁定時調用。
Communicating with the Activity
盡管Fragment對象獨立於activity對象,它可以被使用於多個activity中,一個給定的fragment實例還是直接被綁定到包含它的activity實例中的。
在fragment中通過getActivity()可以獲取activity實例,然后與activity中的成員進行交互操作。
比如:
View listView = getActivity().findViewById(R.id.list);
同樣的,activity可以通過FragmentManager獲取fragment的引用,例如:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
Creating event callbacks to the activity
在一些實例中,可能需要fragment和activity共享events。一個好的方法是在fragment中定義回調接口,而在activity中實現它。當activity通過接口獲得回調時,它就可以與其它fragment在必要的時候共享信息。
例如:一個activity中有兩個fragment。一個顯示文章列表(fragment A),一個顯示具體的文章內容(fragment B)。A必須告知activity用戶選取了哪一篇文章,然后B從activity中獲知這一信息以顯示對應的文章內容。在這一實例中,OnArticleSelectedListener接口在A中聲明:
public static class FragmentA extends ListFragment { ... // Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } OnArticleSelectedListener mListener; ... @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnArticleSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); } } ... }
在activity中我們需要實現這個OnArticleSelectedListener接口,並復寫onArticleSelected()函數通知B響應響應的事件。為了保證activity實現了這一接口,A的onAttach()回調初始化了OnArticleSelectedListener接口把activity傳遞過來。
Adding items to the Action Bar
通過onCreateOptionsMenu(),fragment可以為activity的Options Menu提供菜單項。為了確保這一方法成功實現回調。必須在onCreate()期間調用setHasOptionsMenu()告知Options Menu fragment要添加菜單項。
通過fragment添加的菜單會添加在已有菜單之后。選中菜單項時,fragment也會接收onOptionsItemSelected()回調。
通過registerForContextMenu()注冊,onCreateContextMenu()接收用戶打開信息,onContextItemSelected()接收用戶點擊信息可以實現Context Menu。
用戶點擊菜單的信息首先傳遞給activity,如果activity不處理,則傳遞給fragment。