雖然網上有不少關於Fragment的文章,但我這裏仍是要寫這篇筆記,由於我在編寫程序的過程當中發現了一個問題,至今未解決,但願獲得你們的幫助;
PS:當我在Fragment中定義一個名爲setIndex(int index)的方法以後,運行程序,就會報錯(打印的錯誤信息顯示錯誤爲找不到這個Fragment對應的類),但當把這個方法的名稱改成其它的名稱以後,程序便可正常運行,個人api level爲17和18;android
先看看Fragment的生命週期方法,其實和Activity基本仍是類似的,瞭解Activity的生命週期,再看Fragment的生命週期方法,也就比較容易理解;
編程
先介紹相關概念api
1、fragment一般做爲宿主activity UI的一部分, 被做爲activity整個view hierarchy的一部分被嵌入,至關於一個輕量級的Activity;dom
(一)、將一個fragment添加到layout,有兩種方法。
一、在Layout文件中,添加一個Fragement對應的節點ide
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <fragment android:id="@+id/main_mf" android:name="com.dbo4.domain.MyFragement" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
二、使用FragmentManager將fragment添加到一個已經存在的ViewGroup
當activity運行的任什麼時候候, 均可以將fragment添加到它的layout.只需簡單的指定一個須要放置fragment的ViewGroup(一般爲FrameLayout).FragmentManager提供了一個FragmentTransaction的API,以實如今activity中操做fragment事務(例如添加,移除,或代替一個fragment)。佈局
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
而後可使用 add() 方法添加一個fragment, 指定要添加的fragment, 和要插入的view.
測試
MyFragment fragment = new MyFragment(); fragmentTransaction.add(R.id.xx_viewgroup, fragment); fragmentTransaction.commit();
兩個參數分別是要放入的ViewGroup, 由resource ID指定和須要添加的fragment。爲了使改變生效,還須調用commit()提交事務. 動畫
(二)、若是須要Fragment顯示菜單,可設置hasOptionsMenu = true;
this
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); menu.add("Ma").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); menu.add("Mb").setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODOreturn super.onOptionsItemSelected(item); }
2、FragmentManagerspa
FragmentManager可以實現管理activity中fragment. 經過調用activity的getFragmentManager()取得它的實例.FragmentManager能夠作以下一些事情:
一、使用findFragmentById() (適用於在layout中提供了一個UI的fragment)或findFragmentByTag()(適用於有或沒有UI的fragment)獲取activity中存在的fragment;
二、將fragment從後臺堆棧中彈出, 使用 popBackStack() (模擬用戶按下BACK 命令);
三、使用addOnBackStackChangeListener()註冊一個監聽後臺堆棧變化的listener.
3、FragmentTransaction
FragmentTransaction提供了對fragment進行添加,移除,替換,以及執行其餘操做的api。每個事務都是同時要執行的一套變化.能夠在一個給定的事務中設置你想執行的全部變化,使用諸如 add(), remove(), 和 replace(),而後, 要給activity應用事務, 還必需要調用 commit().
在調用commit()以前, 你可能想調用 addToBackStack(),將事務添加到一個fragment事務的back stack. 這個back stack由activity管理, 並容許用戶經過按下 BACK 按鍵返回到前一個fragment狀態.
ft = fm.beginTransaction();
ft.replace(R.id.cont, new Fragment2());
ft.addToBackStack("f2");
ft.commit();
/************************************/
ft = fm.beginTransaction();
ft.replace(R.id.cont, new Fragment3());
ft.commit();
經過調用 addToBackStack(), replace事務被保存到back stack, 所以用戶能夠回退事務,並經過按下BACK按鍵帶回前一個fragment.
執行上面兩個方法執行的Fragment2的生命週期方法爲:
onAttach -- onCreate -- onCreateView -- onActivityCreated -- onStart -- onResume --
onPause -- onStop -- onDestoryView --
onCreateView -- onActivityCreated -- onStart -- onResume --
若是添加多個變化到事務(例如add()或remove())並調用addToBackStack(), 而後在調用commit()以前的全部應用的變化會被做爲一個單個事務添加到後臺堆棧, BACK按鍵會將它們一塊兒回退.當執行一個移除fragment的事務時, 若是沒有調用 addToBackStack(), 那麼當事務提交後, 那個fragment會被銷燬,而且用戶不能導航回到它。反之,好比當移除一個fragment時,若是調用了 addToBackStack(), 那麼fragment會被中止, 若是用戶導航回來,它將會被恢復.
若是添加多個fragment到同一個容器,那麼添加的順序決定了它們在view hierachy中顯示的順序.對於每個fragment事務, 若是須要添加一個事務動畫, 能夠經過在提交事務以前調用setTransition()實現.
實際上,調用 commit() 並不當即執行事務.偏偏相反, 它將事務安排排期, 一旦準備好, 就在activity的UI線程上運行(主線程).若是有必要, 能夠在UI線程中調用 executePendingTransactions() 來當即執行由commit()提交的事務. 但這麼作一般沒必要要, 除非事務是其餘線程中的job的一個從屬.
只能在activity保存它的狀態(當用戶離開activity)以前使用commit()提交事務.若是試圖在那個點以後提交, 會拋出一個異常.這是由於若是activity須要被恢復, 提交以後的狀態可能會丟失.對於以爲能夠丟失提交的情況, 使用 commitAllowingStateLoss().
4、Fragment之間的通訊
Fragment之間通訊,我分爲兩種狀況,一是兩個Fragment同時在一個activity中,二是兩個Fragment不一樣時存在在前臺顯示;
(一)、同時顯示:對於同時添加顯示於activity的狀況,比較簡單,下面是一個例子
>>.佈局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" tools:context=".MainActivity" > <fragment android:id="@+id/fragment1" android:name="com.fragment.Fragment1" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" /> <fragment android:id="@+id/fragment2" android:name="com.fragment.Fragment2" android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout>
.佈局內容
<Button android:id="@+id/modify" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="修改TextView" /> <!--frag1對應佈局內容--> <TextView android:id="@+id/value" android:layout_width="match_parent" android:layout_height="match_parent" /> <!--frag2對應佈局內容-->
.Fragment1
public class Fragment1 extends Fragment implements OnClickListener { /** * 當fragment被建立的時候調用此方法,返回當前fragment顯示的內容 */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fig1, null); Button btn = (Button) v.findViewById(R.id.modify); btn.setOnClickListener(this); return v; } @Override public void onClick(View v) { Fragment2 f2 = (Fragment2) getActivity().getFragmentManager().findFragmentById(R.id.fragment2); f2.setText("測試修改TextView值"); } }
.Fragment2
public class Fragment2 extends Fragment { private TextView tv;
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fig2, null); tv = (TextView) v.findViewById(R.id.value); return v; } public void setText(String str) { tv.setText(str); } }