Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發之Fragment詳解

Android開發之Fragment詳解

編輯:關於Android編程

Android開發之Fragment學習

1.簡介:

Fragment是Android 3.0引入的新API。 Fragment代表了 Activity的子模塊,因此可以把Fragment理解成Activity片段。Fragment用於自己的生命周期,也可以接受它自己的輸入事件。

Fragment必須被“嵌入” Activity中使用,因此雖然Fragment也擁有自己的生命周期,但Fragment的生命周期會受它所在的Activity的生命周期的控制。例如,當Activity暫停時,該Activity內的所有Fragment都會暫停;當Activity被銷毀時,該Activity內的所有Fragment 都會被銷毀,只有當該Activity處於活動狀態時,程序員可通過方法獨立地操作Fragment。

2.Fragment的幾個特征:

1) Fragment總是作為Activity界面的組成部分,Fragment可調用getActivity()方法獲取它所在的 Activity, Activity調用FragmentManager 的findFragmentByld()或findFragmentByTag()方法來獲取Fragment。

2) 在Activity 運行過程中,可調用 FragmentManager 的add()、remove()、replace()方法動態地添加、刪除或替換Fragment。

3) —個Activity可以同時組合多個Fragment;反過來,一個Fragment也可被多 Activity 復用。

4) Fragment可以響應自己的輸入事件,並擁有自己的生命周期,但它們的生命周期直接被其所屬的Activity的生命周期控制。

Android 3.0引入Fragment的初衷是為了適應大屏幕的平板電腦,由於平板電腦的屏幕比手機屏蒂更大,因此可以容納更多的UI組件,且這些UI組件之間存在交互關系。Fragment 簡化了大屏幕UI的設計,它不需要開發者管理組件包含關系的復雜變化,開發者使用Fragment對UI組件進行分組、模塊化管理,可以更方便地在運行過程中動態更新Activity 的用戶界面。

例如:有如下新聞浏覽界面,該界面需要在屏幕左邊顯示新聞列表,並在屏幕右邊顯示新聞內容,此時就可以在Activity中顯示兩個並排的Fragment左邊的Fragment顯示新聞列表,右邊的Fragment顯示新聞內容。由於每個Fragment擁有自己的生命周期,並可響應用戶輸入事件,因此可以非常方便地實現:當用戶單擊左邊列表的指定新聞時,右Fragment 顯示相應的新聞內容。下圖左邊的“平板電腦”部分顯示了這種Ul界面fragments

通過使用上面的Fragment設計機制,可以取代傳統的讓一個Activity顯示新聞列表,一個Activity顯示新文內容的設計。

由於Fragment是可復用的組件,因此如果需要在正常尺寸的手機屏幕上運行該應用,可以改為使用兩個 Activity,ActivityA 包含 FragmentA、ActivityB 包含 FragmentB。其中 ActivityA 僅包含顯示文章列表FragmentA,而當用戶選擇一篇文章時,它會啟動包含新聞內容的 ActivityB,如上圖右邊的“手機,部分。由此可見,Fragment可以很好地支持上圖所示的兩種設計模式。

3.創建Fragment

與創建Activity類似,開發者實現的Fragment必須繼承Fragment基類,Android提供了 如下圖所示的Fragment繼承體系。

Fragment結構

開發者實現的Fragment,可以根據需要繼承上圖所示的Fragment基類或它的任意子類。接下來,實現Fragment與實現Activity非常相似,它們都需要實現與Activity類似的回調方法,例如onCreate()、onCreateView()、onStart()、onResume()、onPause()、onStop()等。

提示:

開發Fragment與開發Activity非常相似,區別只是開發Activity需要繼承Activity或其子類;但開發Fragment需要繼承Fragment及其子類.與此同時,只要將原來寫在Activity回調方法的代碼“移到”Fragment的回調方法中即可。

通常來說,創建Fragment通常需要實現如下三個方法。

1) onCreate():系統創建Fragment對象後回調該方法,實現代碼中只初始化想要在 Fragment中保持的必要組件,當fragment被暫停或者停止後可以恢復。

2) onCreateView():當Fragment繪制界面組件時會回調該方法。該方法必須返回一個View,該View也就是該Fragment所顯示的View。

3) onPause():當用戶離開該Fragment時將會回調該方法。

對於大部分Fragment而言,通常都會重寫上面這三個方法。但是實際上開發者可以根據需要重寫Fragment的任意回調方法,後面將會詳細介紹Fragment的生命周期及其回調方法為了控制Fragment顯示的組件,通常需要重寫onCreateView()方法,該方法返回的View 將作為該Fragment顯示的View組件。當Fragment繪制界面組件時將會回調該方法。

例如如下方法片段:

// 重寫該方法,該方法返回的View將作為Fragment顯示的組件

@Override

public View onCreateView(LayoutInflater inflater

, ViewGroup container, Bundle savedInstanceState)

{

// 加載/res/layout/目錄下的fragment_book_detail.xml布局文件

View rootView = inflater.inflate(R.layout.fragment_book_detail,

container, false);

if (book != null)

{

// 讓book_title文本框顯示book對象的title屬性

((TextView) rootView.findViewById(R.id.book_title))

.setText(book.title);

// 讓book_desc文本框顯示book對象的desc屬性

((TextView) rootView.findViewById(R.id.book_desc))

.setText(book.desc);

}

return rootView;

}

實例:開發發顯示圖書詳情的Fragment

下面Fragment將會顯示加載一份簡單的界面布局文件,並根據傳入的參數來更新界面組件該Fragment的代碼如下。

3.1創建Fragment:

public class BookDetailFragment extends Fragment

{

public static final String ITEM_ID = "item_id";

// 保存該Fragment顯示的Book對象

BookContent.Book book;

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

// 如果啟動該Fragment時包含了ITEM_ID參數

if (getArguments().containsKey(ITEM_ID))

{

book = BookContent.ITEM_MAP.get(getArguments()

.getInt(ITEM_ID)); //①

}

}

// 重寫該方法,該方法返回的View將作為Fragment顯示的組件

@Override

public View onCreateView(LayoutInflater inflater

, ViewGroup container, Bundle savedInstanceState)

{

// 加載/res/layout/目錄下的fragment_book_detail.xml布局文件

View rootView = inflater.inflate(R.layout.fragment_book_detail,

container, false);

if (book != null)

{

// 讓book_title文本框顯示book對象的title屬性

((TextView) rootView.findViewById(R.id.book_title))

.setText(book.title);

// 讓book_desc文本框顯示book對象的desc屬性

((TextView) rootView.findViewById(R.id.book_desc))

.setText(book.desc);

}

return rootView;

}

}

3.2創建ListFragment:

public class BookDetailFragment extends Fragment

{

public static final String ITEM_ID = "item_id";

// 保存該Fragment顯示的Book對象

BookContent.Book book;

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

// 如果啟動該Fragment時包含了ITEM_ID參數

if (getArguments().containsKey(ITEM_ID))

{

book = BookContent.ITEM_MAP.get(getArguments()

.getInt(ITEM_ID)); //①

}

}

// 重寫該方法,該方法返回的View將作為Fragment顯示的組件

@Override

public View onCreateView(LayoutInflater inflater

, ViewGroup container, Bundle savedInstanceState)

{

// 加載/res/layout/目錄下的fragment_book_detail.xml布局文件

View rootView = inflater.inflate(R.layout.fragment_book_detail,

container, false);

if (book != null)

{

// 讓book_title文本框顯示book對象的title屬性

((TextView) rootView.findViewById(R.id.book_title))

.setText(book.title);

// 讓book_desc文本框顯示book對象的desc屬性

((TextView) rootView.findViewById(R.id.book_desc))

.setText(book.desc);

}

return rootView;

}

}

4.Fragmemt與Activity通信

為了在activity中顯示Fragment還必須將Fragment添加到activity中。

4.1將Fragment添加到activity中有如下兩種方式:

1) 在布局文件中添加:在布局文件中使用元素添加Fragment,其中的android:name屬性必須指定Fragment的實現類。

2) 在Java代碼中添加:在Java代碼中通過FragmentTransaction對象的relpace()或add()方法來替換或添加Fragment。

提示:Activity的getFragmentManager()方法返回FragmentManager,通過調用FragmentManager的beginTransaction()方法獲取FragmentTransaction對象。

Activity的布局文件:

"1.0" encoding="utf-8"?>

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="horizontal"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginLeft="16dp"

android:layout_marginRight="16dp"

android:divider="?android:attr/dividerHorizontal"

android:showDividers="middle">

android:name="com.jph.fragmentdemo.BookListFragment"

android:id="@+id/book_list"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="1" />

<frameLayout android:id="@+id/book_detail_container"

android:layout_width="0dp"

android:layout_height="match_parent"

android:layout_weight="3" />

Activity代碼:

public class SelectBookActivity extends Activity implements

BookListFragment.Callbacks

{

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

// 加載/res/layout目錄下的main.xml布局文件

setContentView(R.layout.main);

}

// 實現Callbacks接口必須實現的方法

@Override

public void onItemSelected(Integer id)

{

// 創建Bundle,准備向Fragment傳入參數

Bundle arguments = new Bundle();

arguments.putInt(BookDetailFragment.ITEM_ID, id);

// 創建BookDetailFragment對象

BookDetailFragment fragment = new BookDetailFragment();

// 向Fragment傳入參數

fragment.setArguments(arguments);

// 使用fragment替換book_detail_container容器當前顯示的Fragment

getFragmentManager().beginTransaction()

.replace(R.id.book_detail_container, fragment).commit(); //①

}

}

上而的程序中①號粗體字代碼就調用了FragmentTransaction的replace()方法動態更新了 ID為book_detail_container容器(也就是前面布局文件中的FrameLayout容器)中顯示的 Fragment。

將Fragment添加到Activity之後,Fragment必須與Activity交互信息,這就需要Fragment能獲取它所在的Activity, Activity也能獲取它所包含的任意的Fragment。可按如下方法進行。

4.2在activity中獲取Fragement,在Fragment中獲取activity的方法:

1) Fragment獲取它所在的Activity:調用Fragment的getActivity()方法即可返回它所在的Activity。

2) Activity 獲取它包含的Fragment:調用 Activity 關聯的 FragmentManager 的 findFragmentByld(int id)或findFragmentByTag(String tag)方法即可獲取指定的 Fragment。

提示:

在界面布局文件中使用元素添加Fragment時,可以為元素指定android:id或android:tag屬性,這兩個屬性都可用於標識該 Fragment,接下來 Activity 將可通過 findFragmentByld(int id)或 findFragmentByTag(String tag)來獲取該 Fragment。

4.3Fragment與Activity可能還需要相互傳遞數據的方式:

1) Activity向Fragment傳遞數據:在Activity中創建Bundle數據包,並調用Fragment 的setArguments(Bundle bundle)方法即可將 Bundle 數據包傳給 Fragment。

2) Fragment向Activity傳遞數據或Activity需要在Fragment運行中進行實時通信: 在Fragment中定義一個內部回調接口,再讓包含該Fragment的Activity實現該回調接口,這樣Fragment即可調用該回調方法將數據傳給Activity。

3) 通過廣播的方式。

5.Fragment 管理與 Fragment 事務

前面介紹了 Activity與Fragment交互相關的內容,其實Activity管理Fragment主要依靠FragmentManger。

5.1FragmentMange的功能:

1) 使用 findFragmentByld()或 findFragmentByTag()方法來獲取指定 Fragment。

2) 調用popBackStack()方法將Fragment從後台找中彈出(模擬用戶按下BACK按鍵)。

3) 調用addOnBackStackChangeListener()注冊個監聽器,用於監聽後台棧的變化。如果需要添加、刪除、替換Fragment,則需要借助FragmentTransaction對象, FragmentTransaction 代表 Activity 對 Fragment 執行的多個改變。

提示:

FragmentTransaction也被翻譯為Fragment事務。與數據庫事務類似的是,數據庫事務代表了對底層數組的多個更新操作;而Fragment事務則代表了Activity對Fragment執行的多個改變操作。

每個FragmentTransaction可以包含多個對Fragment的修改,比如包含調用多個add()、replace()、和remove()操作,最後調用commit()提交事務即可。

在調用commit()之前,開發者也可調用addToBackStack()將事務添加到back棧,該棧由Activity負責管理,這樣允許用戶按BACK按鍵返回到前一個Fragment狀態。

//創建一個新的Fragment並打開事務

Fragment newFragment = new ExampleFragment();

FragmentTransaction transaction = getFragmentManager().beginTransaction();

//替換該界面中fragment_container容器內的Fragment

transaction.replace(R.id.fragment_container, newFragment);

//將事務添加到back棧,允許用戶按back按鍵返回到替換Fragment之前的狀態 transaction.addToBackStack(null);

//提交事務

transaction.commit();

在上面的示例代碼中,newFragment替換了當前界面布 局中ID為fragment_container的容器內的Fragment,由於程序調用了addToBackStack()將該replace操作添加到了back棧中,因此用戶可以通過按下BACK按鍵返回替換之前的狀態。

6.Fragment的生命周期:

與Activity類似的是,Fragment也存在如下狀態。

? 活動狀態:當前Fragment位於前台,用戶可見,可以獲得焦點。

? 暫停狀態:其他Activity位於前台,該Fragment依然可見,只是不能獲得焦點。

? 停止狀態:該Fragment不可見,失去焦點。

? 銷毀狀態:該Fragment被完全刪除,或該Fragment所在的Activity被結束。

fragment的生命周期

從上圖可以看出,在Fragment的生命周期中,如下方法 會被系統回調。

? onAttach():當該Fragment被添加到Activity時被回調。該方法只會被調用一次。

? onCreate(Bundle savedStatus):創建 Fragment 時被回調。該方法只會被調用一次。

? onCreateView():每次創建、繪制該Fragment的 View 組件時回調該方法,Fragment將會顯示該方法返回的 View組件。

? onActivityCreated():當 Fragment 所在的 Activity 被啟動完成後回調該方法。

? onStart():啟動 Fragment 時被回調。

? onResume():恢復 Fragment 時被回調,onStart()方法後一定會回調()onResume()方法。

? onPause():暫停Fragment 時被回調。

? onStop():停止Fragment 時被回調。

? onDestroyView():銷毀該 Fragment 所包含的 View 組件時調用。

? onDestroy():銷毀Fragment時被回調。該方法只會被調用一次。

? onDetach():將該 Fragment 從 Activity 中被刪除、被替換完成時回調該方法,onDestroy()方法後一定會回調onDetach()方法。該方法只會被調用一次。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved