一塊兒學Android之Fragment

概述

本文以一個簡單的小例子,簡述在Android開發中,Fragment的常見用法,僅供學習分享使用,若有不足之處,還請指正。android

什麼是Fragment?

Fragment表明一個功能或者用戶界面的一部分。一個Activity能夠由多個Fragment組成多窗格UI,一個Fragment也能夠重用在多個Activity中。你能夠把Fragment做爲Activity的一個模塊,它有本身的生命週期,接收本身的 輸入事件,當Activity運行時能夠動態的添加和刪除,相似於‘sub Activity’。api

Fragment必須始終做爲Activity的一部分,它的生命週期受到宿主Activity生命週期的影響。如:當Activity暫停時,其包含的全部Fragment也都會暫停;當Activity銷燬時,其包含的全部Fragment也會被銷燬;可是當Activity運行時,你能夠獨立的操做Fragment,如添加和刪除;
ide

Fragment設計理念

androidandroid 3.0api等級11)中引入了Fragment,主要是爲了支持大屏幕(如平板電腦)上更具活力和靈活性的ui設計。由於平板電腦的屏幕比手機大得多,因此有更多的空間來組合和交換ui組件。經過將Activity的佈局劃分爲Fragment,就可以在程序運行時修改Activity的外觀,並在由活動管理的後堆棧中保存這些更改。模塊化

例如,一個新聞應用App,能夠用一個Fragment顯示左側的文章列表,用另外一個Fragment顯示右側的文章----兩個Fragment同時出如今一個Activity中,而每一個Fragment都有本身的生命週期及回調方法集合,並處理本身的用戶輸入事件。所以,用戶能夠在相同的Activity中選擇文章,而不是分開單獨使用不一樣的Activity,如圖1的平板版式所示。函數

應該將每一個Fragment設計成模塊化和可重用的頁面組件。也就是說,因爲每一個Fragment有本身的生命週期,回調函數,佈局和行爲,因此能夠在多個Activity中包含同一個FragmentFragment應該設計爲重用,避免在一個Fragment中直接操做引用另外一個Fragment。這一點特別重要,由於一個模塊化的Fragment能夠經過不一樣的組合來適應不一樣屏幕大小。在應用程序同時支持平板電腦和手機時,能夠在不一樣的佈局配置中重用Fragment,以根據屏幕空間優化用戶體驗。佈局

1一個例子,說明兩個由Fragment定義的UI模塊如何在平板上設計爲一個Activity中顯示,但在手機上則分開顯示。學習

涉及知識點

涉及知識點以下:優化

  • Fragment 全部自定義Fragment的父類。
  • FragmentManager Fragment管理器對象,用來動態新增和替換Fragmentd對象。
  • FragmentTransaction 表示一個Fragment管理事務,必須以commit()結束。
  • onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 方法,返回Fragment對應的佈局視圖。
  • getFragmentManager() 返回一個Fragment管理器對象。

建立一個Fragment

若是要建立一個自定義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生命週期

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: 
View Code

Activity中添加Fragment

Fragment是做爲Activity的一部分而存在的,有兩種方法能夠將Fragment添加到Activity的佈局文件中:

靜態添加Fragment

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:

  • 提供android:id帶有惟一的ID屬性。
  • 提供android:tag帶有惟一字符串的標籤屬性。
  • 若是沒有提供前面兩個中的任何一個,系統將使用容器視圖的id。
動態添加Fragment

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之間的傳值

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中,實現鬆耦合。

備註

滄海月明珠有淚,藍田日暖玉生煙。

相關文章
相關標籤/搜索