本文以一個簡單的小例子,簡述在Android開發中,Fragment的常見用法,僅供學習分享使用,若有不足之處,還請指正。android
Fragment表明一個功能或者用戶界面的一部分。一個Activity能夠由多個Fragment組成多窗格UI,一個Fragment也能夠重用在多個Activity中。你能夠把Fragment做爲Activity的一個模塊,它有本身的生命週期,接收本身的 輸入事件,當Activity運行時能夠動態的添加和刪除,相似於‘sub Activity’。api
Fragment必須始終做爲Activity的一部分,它的生命週期受到宿主Activity生命週期的影響。如:當Activity暫停時,其包含的全部Fragment也都會暫停;當Activity銷燬時,其包含的全部Fragment也會被銷燬;可是當Activity運行時,你能夠獨立的操做Fragment,如添加和刪除;
ide
android在android 3.0(api等級11)中引入了Fragment,主要是爲了支持大屏幕(如平板電腦)上更具活力和靈活性的ui設計。由於平板電腦的屏幕比手機大得多,因此有更多的空間來組合和交換ui組件。經過將Activity的佈局劃分爲Fragment,就可以在程序運行時修改Activity的外觀,並在由活動管理的後堆棧中保存這些更改。模塊化
例如,一個新聞應用App,能夠用一個Fragment顯示左側的文章列表,用另外一個Fragment顯示右側的文章----兩個Fragment同時出如今一個Activity中,而每一個Fragment都有本身的生命週期及回調方法集合,並處理本身的用戶輸入事件。所以,用戶能夠在相同的Activity中選擇文章,而不是分開單獨使用不一樣的Activity,如圖1的平板版式所示。函數
應該將每一個Fragment設計成模塊化和可重用的頁面組件。也就是說,因爲每一個Fragment有本身的生命週期,回調函數,佈局和行爲,因此能夠在多個Activity中包含同一個Fragment。Fragment應該設計爲重用,避免在一個Fragment中直接操做引用另外一個Fragment。這一點特別重要,由於一個模塊化的Fragment能夠經過不一樣的組合來適應不一樣屏幕大小。在應用程序同時支持平板電腦和手機時,能夠在不一樣的佈局配置中重用Fragment,以根據屏幕空間優化用戶體驗。佈局
圖1一個例子,說明兩個由Fragment定義的UI模塊如何在平板上設計爲一個Activity中顯示,但在手機上則分開顯示。學習
涉及知識點以下:優化
若是要建立一個自定義Fragment,必須建立一個Fragment的子類,而且必須實現onCreateView()方法,經過LayoutInflater將佈局文件填充到Fragment中,以下所示:ui
1 public class RightFragment extends Fragment { 2 3 private TextView tvMsg; 4 5 @Override 6 public View onCreateView(LayoutInflater inflater, ViewGroup container, 7 Bundle savedInstanceState) { 8 // Inflate the layout for this fragment 9 Log.i("TAG", "------------Right-----------onCreateView: "); 10 View view= inflater.inflate(R.layout.fragment_right, container, false); 11 tvMsg= (TextView) view.findViewById(R.id.tv_msg); 12 return view; 13 } 14 }
Fragment的生命週期和Activity的生命週期有許多類似之處。以下圖所示:this
Activity和Fragment回調函數輸出內容以下所示:
1 05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onAttach: 2 05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onCreate: 3 05-30 22:16:02.207 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onCreateView: 4 05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onAttach: 5 05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onCreate: 6 05-30 22:16:02.216 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onCreateView: 7 05-30 22:16:02.218 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onCreate: 8 05-30 22:16:02.218 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onActivityCreated: 9 05-30 22:16:02.218 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onActivityCreated: 10 05-30 22:16:02.219 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onStart: 11 05-30 22:16:02.219 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onStart: 12 05-30 22:16:02.219 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onStart: 13 05-30 22:16:02.224 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onResume: 14 05-30 22:16:02.224 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onResume: 15 05-30 22:16:02.224 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onResume: 16 05-30 22:16:06.188 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onPause: 17 05-30 22:16:06.188 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onPause: 18 05-30 22:16:06.189 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onPause: 19 05-30 22:16:06.756 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onStop: 20 05-30 22:16:06.756 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onStop: 21 05-30 22:16:06.756 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onStop: 22 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDestroyView: 23 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDestroy: 24 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Left-----------onDetach: 25 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDestroyView: 26 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDestroy: 27 05-30 22:16:06.757 29479-29479/com.hex.demofragment I/TAG: ------------Right-----------onDetach: 28 05-30 22:16:06.757 29479-29479/com.hex.demofragment E/TAG: ------------Main-----------onDestroy:
Fragment是做爲Activity的一部分而存在的,有兩種方法能夠將Fragment添加到Activity的佈局文件中:
在Activity的佈局文件中直接聲明Fragment,在這種狀況下,您能夠爲Fragment指定佈局屬性,就像它是視圖控件同樣。例如,這裏是包含兩個片斷的活動的佈局文件:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 android:orientation="horizontal" 8 tools:context="com.hex.demofragment.MainActivity"> 9 <fragment 10 android:tag="left" 11 android:id="@+id/left_fragment" 12 class="com.hex.demofragment.LeftFragment" 13 android:layout_width="200dp" 14 android:layout_height="match_parent" 15 android:layout_weight="1"></fragment> 16 <fragment 17 android:tag="right" 18 android:id="@+id/right_fragment" 19 class="com.hex.demofragment.RightFragment" 20 android:layout_width="300dp" 21 android:layout_height="match_parent" 22 android:layout_weight="2"></fragment> 23 </LinearLayout>
如上所示:class 表示須要在視圖中顯示的fragment類,當系統建立Activity時,就會實例化Fragment並調用onCreateView方法,顯示對應的佈局文件。android:name和class表示的功能是同樣的,須要其中一個便可。
備註:每一個Fragment都須要一個惟一的標識符,若是Activity被從新啓動的話,系統能夠用它來恢復Fragment。
有三種方法能夠爲Fragment提供id:
當Activity處於運行狀態時,均可以將Fragment添加到頁面佈局中,只須要有一個ViewGroup用來存放便可。以下所示:
1 //FragmentManager是Activity內部用來與Fragment進行交互的接口 2 FragmentManager fm = getFragmentManager(); 3 FragmentTransaction ft=fm.beginTransaction(); 4 //將左側Fragment和Frame控件關聯起來 5 left=new LeftFragment(); 6 left.setTransData(transData); 7 ft.add(R.id.fl_left,left); 8 right=new RightFragment(); 9 ft.add(R.id.fl_right,right); 10 ft.commit();
若是要管理Activity中的Fragment,須要使用碎片管理器(FragmentManager),能夠經過Activity中的getFragmentManager()方法來得到對象。
Fragment 做爲獨立的可重用的用戶模塊,應儘可能避免相互引用,因此如何實現之間相互傳值,就顯得很重要,本文采用接口回調的方式進行傳值。
具體以下:
一、定義一個傳值接口,以下所示:
1 public interface ITransData { 2 public void transData(Bundle bundle); 3 }
二、在須要傳值的Fragment中,定義接口屬性對象,以下所示,左側(LeftFragment):
1 private ITransData mTransData; 2 3 public void setTransData(ITransData transData){ 4 this.mTransData=transData; 5 } 6 7 @Override 8 public View onCreateView(LayoutInflater inflater, ViewGroup container, 9 Bundle savedInstanceState) { 10 11 View view = inflater.inflate(R.layout.fragment_left, container, false); 12 Button tv= (Button) view.findViewById(R.id.bn_left); 13 tv.setOnClickListener(new View.OnClickListener() { 14 @Override 15 public void onClick(View v) { 16 if(mTransData!=null){ 17 Bundle bundle=new Bundle(); 18 bundle.putString("name","我是左邊"); 19 mTransData.transData(bundle); 20 } 21 } 22 }); 23 return view; 24 }
三、在Activity中,實現ITransData接口,並傳給LeftFragment進行調用:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState); 4 setContentView(R.layout.activity_main2); 5 ITransData transData=new TransData(); 6 //FragmentManager是Activity內部用來與Fragment進行交互的接口 7 FragmentManager fm = getFragmentManager(); 8 FragmentTransaction ft=fm.beginTransaction(); 9 //將左側Fragment和Frame控件關聯起來 10 left=new LeftFragment(); 11 left.setTransData(transData);//將接口傳遞給LeftFragment 12 ft.add(R.id.fl_left,left); 13 right=new RightFragment(); 14 ft.add(R.id.fl_right,right); 15 ft.commit(); 16 }
四、在接口函數中調用獲取左側傳回來的值,並調用RightFragment方法傳遞值。
1 protected class TransData implements ITransData 2 { 3 @Override 4 public void transData(Bundle bundle) { 5 String name=bundle.getString("name","空"); 6 if(right!=null){ 7 right.setTransData(name); 8 } 9 } 10 }
至此Fragment之間傳值介紹完畢,總結一句話:Fragment經過接口傳值,接口的實如今Activity中,實現鬆耦合。
滄海月明珠有淚,藍田日暖玉生煙。