Android Fragment 詳解
Fragment產生原因:
同時適配手機和平板、UI和邏輯的共享。
介紹:
- Fragment也會被加入回退棧中。
- Fragment擁有自己的生命週期和接受、處理使用者的事件。
- 可以動態的新增、替換和移除某個Fragment。
- 必須依存於Activity
生命週期
Fragment依附於Activity的生命狀態
Fragment生命週期方法含義:
public void onAttach(Context context)
onAttach方法會在Fragment於視窗關聯後立刻呼叫。從該方法開始,就可以通過Fragment.getActivity方法獲取與Fragment關聯的視窗物件,但因為Fragment的控制元件未初始化,所以不能夠操作控制元件。
public void onCreate(Bundle savedInstanceState)
在呼叫完onAttach執行完之後立刻呼叫onCreate方法,可以在Bundle物件中獲取一些在Activity中傳過來的資料。通常會在該方法中讀取儲存的狀態,獲取或初始化一些資料。在該方法中不要進行耗時操作,不然視窗不會顯示。
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
該方法是Fragment很重要的一個生命週期方法,因為會在該方法中建立在Fragment顯示的View,其中inflater是用來裝載佈局檔案的,container是<fragment>
public void onViewCreated(View view,Bundle savedInstanceState)
Android在建立完Fragment中的View物件之後,會立刻回撥該方法。其種view引數就是onCreateView中返回的view,而bundle物件用於一般用途。
public void onActivityCreated(Bundle savedInstanceState)
在Activity的onCreate方法執行完之後,Android系統會立刻呼叫該方法,表示視窗已經初始化完成,從這一個時候開始,就可以在Fragment中使用getActivity().findViewById(Id);來操控Activity中的view了。
public void onStart()
這個沒啥可講的,但有一個細節需要知道,當系統呼叫該方法的時候,fragment已經顯示在ui上,但還不能進行互動,因為onResume方法還沒執行完。
public void onResume()
該方法為fragment從建立到顯示Android系統呼叫的最後一個生命週期方法,呼叫完該方法時候,fragment就可以與使用者互動了。
public void onPause()
fragment由活躍狀態變成非活躍狀態執行的第一個回撥方法,通常可以在這個方法中儲存一些需要臨時暫停的工作。如儲存音樂播放進度,然後在onResume中恢復音樂播放進度。
public void onStop()
當onStop返回的時候,fragment將從螢幕上消失。
public void onDestoryView()
該方法的呼叫意味著在 onCreateView
中建立的檢視都將被移除。
public void onDestroy()
Android在Fragment不再使用時會呼叫該方法。
public void onDetach()
為Fragment生命週期中的最後一個方法,當該方法執行完後,Fragment與Activity不再有關聯。
Fragment與Activity之間的互動
Fragment與Activity之間的互動可以通過Fragment.setArguments(Bundle args)
以及Fragment.getArguments()
來實現。
Fragment狀態的持久化
方法一:
可以通過protected void onSaveInstanceState(Bundle outState)
,protected void onRestoreInstanceState(Bundle savedInstanceState)
狀態儲存和恢復的方法將狀態持久化。
方法二:
我們只需要將Fragment在Activity中作為一個變數整個儲存,只要儲存了Fragment,那麼Fragment的狀態就得到儲存了。
FragmentManager.putFragment(Bundle bundle, String key, Fragment fragment)
是在Activity中儲存Fragment的方法。FragmentManager.getFragment(Bundle bundle, String key)
是在Activity中獲取所儲存的Frament的方法。
很顯然,key就傳入Fragment的id,fragment就是你要儲存狀態的fragment,但,我們注意到上面的兩個方法,第一個引數都是Bundle,這就意味著FragmentManager是通過Bundle去儲存Fragment的。但是,這個方法僅僅能夠儲存Fragment中的控制元件狀態,比如說EditText中使用者已經輸入的文字(注意!在這裡,控制元件需要設定一個id,否則Android將不會為我們儲存控制元件的狀態),而Fragment中需要持久化的變數依然會丟失,但依然有解決辦法,就是利用方法一!
下面給出狀態持久化的事例程式碼:
/** Activity中的程式碼 **/
FragmentB fragmentB;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_activity);
if( savedInstanceState != null ){
fragmentB = (FragmentB) getSupportFragmentManager().getFragment(savedInstanceState,"fragmentB");
}
init();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
if( fragmentB != null ){
getSupportFragmentManager().putFragment(outState,"fragmentB",fragmentB);
}
super.onSaveInstanceState(outState);
}
/** Fragment中儲存變數的程式碼 **/
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
AppLog.e("onCreateView");
if ( null != savedInstanceState ){
String savedString = savedInstanceState.getString("string");
//得到儲存下來的string
}
View root = inflater.inflate(R.layout.fragment_a,null);
return root;
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("string","anAngryAnt");
super.onSaveInstanceState(outState);
}
靜態的使用Fragment
- 繼承Fragment,重寫onCreateView決定Fragment的佈局
- 在Activity中宣告此Fragment,就和普通的View一樣
Fragment常用的API
- android.support.v4.app.Fragment 主要用於定義Fragment
- android.support.v4.app.FragmentManager主要用於在Activity中操作Fragment,可以使用FragmentManager.findFragmenById,FragmentManager.findFragmentByTag等方法去找到一個Fragment
- android.support.v4.app.FragmentTransaction 保證一些列Fragment操作的原子性,熟悉事務這個詞
- 主要的操作都是FragmentTransaction的方法(一般我們為了向下相容,都使用support.v4包裡面的Fragment)
- 主要的操作都是FragmentTransaction的方法
FragmentTransaction transaction = fm.benginTransatcion();//開啟一個事務 transaction.add() //往Activity中新增一個Fragment transaction.remove() //從Activity中移除一個Fragment,如果被移除的Fragment沒有新增到回退棧(回退棧後面會詳細說),這個Fragment例項將會被銷燬。 transaction.replace() //使用另一個Fragment替換當前的,實際上就是remove()然後add()的合體~ transaction.hide() //隱藏當前的Fragment,僅僅是設為不可見,並不會銷燬 transaction.show() //顯示之前隱藏的Fragment detach() //當fragment被加入到回退棧的時候,該方法與*remove()*的作用是相同的, //反之,該方法只是將fragment從檢視中移除, //之後仍然可以通過*attach()*方法重新使用fragment, //而呼叫了*remove()*方法之後, //不僅將Fragment從檢視中移除,fragment還將不再可用。 attach() //重建view檢視,附加到UI上並顯示。 transatcion.commit() //提交一個事務
管理Fragment回退棧
- 跟蹤回退棧狀態,我們通過實現*
OnBackStackChangedListener
*介面來實現回退棧狀態跟蹤,具體如下
public class XXX implements FragmentManager.OnBackStackChangedListener
/** 實現介面所要實現的方法 **/
@Override
public void onBackStackChanged() {
//do whatevery you want
}
/** 設定回退棧監聽介面 **/
getSupportFragmentManager().addOnBackStackChangedListener(this);
- 管理回退棧
-
FragmentTransaction.addToBackStack(String)
--將一個剛剛新增的Fragment加入到回退棧中 -
getSupportFragmentManager().getBackStackEntryCount()--獲取回退棧中實體數量
-
getSupportFragmentManager().popBackStack(String name, int flags)--根據name立刻彈出棧頂的fragment
-
getSupportFragmentManager().popBackStack(int id, int flags) --根據id立刻彈出棧頂的fragment
福利
掃描二維碼,下載銀聯旗下APP-雲閃付,註冊綁卡,即可領紅包(8.8~2018元)!
每天都能領!!!
每天都能領!!!
每天都能領!!!