Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android] Fragment 全解析

[Android] Fragment 全解析

編輯:關於Android編程

1.概述

  Fragment是Activity中用戶界面的一個行為或者是一部分。主要是支持在大屏幕上動態和更為靈活的去組合或是交換UI組件,通過將activity的布局分割成若干個fragment,可以在運行時編輯activity的呈現,並且那些變化會被保存在由activity管理的後台棧裡面。

  Fragment必須總是被嵌入到一個activity之中,並且fragment的生命周期直接受其宿主activity的生命周期的影響。你可以認為fragment是activity的一個模塊零件,它有自己的生命周期,接收它自己的輸入事件,並且可以在activity運行時添加或者刪除。

  應該將每一個fragment設計為模塊化的和可復用化的activity組件。也就是說,你可以在多個activity中引用同一個fragment,因為fragment定義了它自己的布局,並且使用它本身生命周期回調的行為。

2.Fragment的生命周期

先看fragment生命周期圖:

這裡寫圖片描述

  fragment所生存的activity生命周期直接影響著fragment的生命周期,由此針對activity的每一個生命周期回調都會引發一個fragment類似的回調。例如,當activity接收到onPause()時,這個activity之中的每個fragment都會接收到onPause()。
  這有Activity的詳細說明

  Fragment有一些額外的生命周期回調方法(創建和銷毀fragment界面).

onAttach()

  當fragment被綁定到activity時調用(Activity會被傳入)。

onCreateView()

  將本身的布局構建到activity中去(fragment作為activity界面的一部分)
  

onActivityCreated()

  當activity的onCreate()函數返回時被調用。

onDestroyView()

  當與fragment關聯的視圖體系正被移除時被調用。

onDetach()

  當fragment正與activity解除關聯時被調用。

當activity接收到它的onCreate()回調時,activity之中的fragment接收到onActivityCreated()回調。

  一旦activity處於resumed狀態,則可以在activity中自由的添加或者移除fragment。因此,只有當activity處於resumed狀態時,fragment的生命周期才可以獨立變化。
  
fragment會在 activity離開恢復狀態時 再一次被activity推入它的生命周期中。

管理fragment生命周期與管理activity生命周期很相像。像activity一樣,fragment也有三種狀態:

Resumed

  fragment在運行中的activity可見。

Paused

  另一個activity處於前台且得到焦點,但是這個fragment所在的activity仍然可見(前台activity部分透明,或者沒有覆蓋全屏)。

Stopped

  fragment不可見。要麼宿主activity已經停止,要麼fragment已經從activity上移除,但已被添加到後台棧中。一個停止的fragment仍然活著(所有狀態和成員信息仍然由系統保留著)。但是,它對用戶來講已經不再可見,並且如果activity被殺掉,它也將被殺掉。

  如果activity的進程被殺掉了,在activity被重新創建時,你需要恢復fragment狀態。可以執行fragment的onSaveInstanceState()來保存狀態(注意在fragment是在onCreate(),onCreateView(),或onActvityCreate()中進行恢復)。

  在生命周期方面,activity與fragment之間一個很重要的不同,就是在各自的後台棧中是如何存儲的。
  當activity停止時,默認情況下activity被安置在由系統管理的activity後台棧中; 
  fragment僅當在一個事務被移除時,通過顯式調用addToBackStack()請求保存的實例,該fragment才被置於由宿主activity管理的後台棧。 

要創建一個fragment,必須創建一個fragment的子類。一般情況下,我們至少需要實現以下幾個fragment生命周期方法:

onCreate()

  在創建fragment時系統會調用此方法。在實現代碼中,你可以初始化想要在fragment中保持的那些必要組件,當fragment處於暫停或者停止狀態之後可重新啟用它們。

onCreateView()

  在第一次為fragment繪制用戶界面時系統會調用此方法。為fragment繪制用戶界面,這個函數必須要返回所繪出的fragment的根View。如果fragment沒有用戶界面可以返回空。

@Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { 

            // Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
        }

inflate()函數需要以下三個參數:

①要inflate的布局的資源ID。 

②被inflate的布局的父ViewGroup。

③一個布爾值,表明在inflate期間被infalte的布局是否應該附上ViewGroup(第二個參數container)。(在這個例子中傳入的是false,因為系統已經將被inflate的布局插入到容器中(container)——傳入true會在最終的布局裡創建一個多余的ViewGroup。) 

onPause()

  系統回調用該函數作為用戶離開fragment的第一個預兆(盡管這並不總意味著fragment被銷毀)。在當前用戶會話結束之前,通常要在這裡提交任何應該持久化的變化(因為用戶可能不再返回)。

3.將fragment添加到activity之中

  可以通過在activity布局文件中聲明fragment,用fragment標簽把fragment插入到activity的布局中,或者是用應用程序源碼將它添加到一個存在的ViewGroup中。 
  
  但fragment並不是一個定要作為activity布局的一部分,fragment也可以為activity隱身工作。

3.1在activity的布局文件裡聲明fragment

  可以像為view一樣為fragment指定布局屬性。例如:


     

        
    

  fragment標簽中的android:name 屬性指定了布局中實例化的Fragment類。

  當系統創建activity布局時,它實例化了布局文件中指定的每一個fragment,並為它們調用onCreateView()函數,以獲取每一個fragment的布局。系統直接在元素的位置插入fragment返回的View。

  注意:每個fragment都需要一個唯一的標識,如果重啟activity,系統可用來恢復fragment(並且可用來捕捉fragment的事務處理,例如移除)。為fragment提供ID有三種方法:

用android:id屬性提供一個唯一的標識。 

用android:tag屬性提供一個唯一的字符串。 

如果上述兩個屬性都沒有,系統會使用其容器視圖(view)的ID。 

3.2通過編碼將fragment添加到已存在的ViewGroup中

  在activity運行的任何時候,你都可以將fragment添加到activity布局中。
  
  要管理activity中的fragment,可以使用FragmentManager。可以通過在activity中調用getFragmentManager()獲得。使用FragmentManager 可以做如下事情,包括:

使用findFragmentById()(用於在activity布局中提供有界面的fragment)或者findFragmentByTag()獲取activity中存在的fragment(用於有界面或者沒有界面的fragment)。  

使用popBackStack()(模仿用戶的BACK命令)從後台棧彈出fragment。  

使用addOnBackStackChangedListener()注冊一個監聽後台棧變化的監聽器。

在Android中,對Fragment的事務操作都是通過FragmentTransaction來執行。操作大致可以分為兩類:

顯示:add() replace() show() attach()  

隱藏:remove() hide() detach() 

說明:
  調用show() & hide()方法時,Fragment的生命周期方法並不會被執行,僅僅是Fragment的View被顯示或者?隱藏。

  執行replace()時(至少兩個Fragment),會執行第二個Fragment的onAttach()方法、執行第一個Fragment的onPause()-onDetach()方法,同時containerView會detach第一個Fragment的View。

  add()方法執行onAttach()-onResume()的生命周期,相對的remove()就是執行完成剩下的onPause()-onDetach()周期。

可以像下面這樣從Activity中取得FragmentTransaction的實例:

FragmentManager fragmentManager = getFragmentManager() 
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

可以用add()函數添加fragment,並指定要添加的fragment以及要將其插入到哪個視圖(view)之中(注意commit事務):

ExampleFragment fragment = new ExampleFragment();
    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();

3.3添加沒有界面的fragment

  也可以使用fragment為activity提供後台動作,卻不呈現多余的用戶界面。

  想要添加沒有界面的fragment ,可以使用add(Fragment, String)(為fragment提供一個唯一的字符串“tag”,而不是視圖(view)ID)。這樣添加了fragment,但是,因為還沒有關聯到activity布局中的視圖(view) ,收不到onCreateView()的調用。所以不需要實現這個方法。 
  
  對於無界面fragment,字符串標簽是唯一識別它的方法。如果之後想從activity中取到fragment,需要使用findFragmentByTag()。 

4.fragment事務後台棧

  在調用commit()之前,可以將事務添加到fragment事務後台棧中(通過調用addToBackStatck())。這個後台棧由activity管理,並且允許用戶通過按BACK鍵回退到前一個fragment狀態。

  下面的代碼中一個fragment代替另一個fragment,並且將之前的fragment狀態保留在後台棧中:

 Fragment newFragment = new ExampleFragment();
 FragmentTransaction transaction = getFragmentManager().beginTransaction();

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

 transaction.commit();

注意:

   如果添加多個變更事務(例如另一個add()或者remove())並調用addToBackStack(),那麼在調用commit()之前的所有應用的變更被作為一個單獨的事務添加到後台棧中,並且BACK鍵可以將它們一起回退。

  當移除一個fragment時,如果調用了addToBackStack(),那麼之後fragment會被停止,如果用戶回退,它將被恢復過來。

  調用commit()並不立刻執行事務,相反,而是采取預約方式,一旦activity的界面線程(主線程)准備好便可運行起來。然而,如果有必要的話,你可以從界面線程調用executePendingTransations()立即執行由commit()提交的事務。

  只能在activity保存狀態(當用戶離開activity時)之前用commit()提交事務。如果你嘗試在那時之後提交,會拋出一個異常。這是因為如果activity需要被恢復,提交後的狀態會被丟失。對於這類丟失提交的情況,可使用commitAllowingStateLoss()

5.與Activity交互

Activity中已經有了該Fragment的引用,直接通過該引用進行交互。

-如果沒引用可以通過調用fragment的函數findFragmentById()或者findFragmentByTag(),從FragmentManager中獲取Fragment的索引,例如:

ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);

在Fragment中可以通過getActivity得到當前綁定的Activity的實例。

創建activity事件回調函數,在fragment內部定義一個回調接口,宿主activity來實現它。

 

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