fragment雜談

銳湃發表於2015-10-22


一、什麼是Fragment   (是一種封裝、重用的思想。)
 中文名“碎片”
 Fragment碎片或者是片段,是使用者介面的一部分。你可以將其看成一個View,
 他有自己的生命週期,接收自己的輸入事件,你可以新增、刪除、替換。
 Fragment必須是依附於Activity之上。
 什麼時候要使用fragment,以及在Activity設計裡面搞幾個fragment,關鍵看“封裝、重用”

二、作用
 1.可以動態和靈活的使用UI;例如根據螢幕大小來選擇載入不同的顯示效果
 2.可以重用(需要分裝);
 3.可以實現程式碼分離;
 ( fragment並不一定必須是activity佈局的一部分;
 也可以將一個fragment作為activity的隱藏的後臺工作者.--不會呼叫onCreateView方法)
三、舉例子
 1)app裡面很多時候需要登入才能進入的一些介面。這時候
 如果使用者沒有登入,先顯示的是登入介面。
 如果使用者已經登入,就顯示的是下單介面or收藏介面等。
 2)平板設計,平板和手機顯示的UI佈局不一樣。
 如何做到一個專案裡面-同樣的功能模組,在手機和平板裡面顯示的效果不一樣?
 (1)如何做到手機和平板使用不同的佈局?
 系統會自動處理。layout/layout-large
 (佈局1:menufragment,  佈局2:menuAfragment,Detailfragment))
 (2)寫一個Activity,在MenuAfragment裡面做判斷--執行不同的處理。

注意:fragment必須要id或者tag;或者都不新增,但是它的父容器必須有要有id

判斷是否是平板:
/**
     * 判斷當前裝置是手機還是平板,程式碼來自 Google I/O App for Android
     * @param context
     * @return 平板返回 True,手機返回 False
     */
    public static boolean isTablet(Context context) {
        return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
    }

xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp

四、使用
 兩種方式:
 1.低版本(<3.0的版本)
  1)導包android-support-v4.jar (在sdk的extra目錄下面)
  android.support.v4.app.Fragment
  2) 寫一個Fragment類 ---繼承Fragment(android.support.v4.app.Fragment)
  至少要重寫onCreateView();----建立一個檢視
  3)將Fragment新增到佈局裡面
  <fragment
     android:name="myfragment的全類名"
  //或者使用class="com.jky.fragment.MyFragment"
  />
  4)將使用該佈局的Activity繼承FragmentActivity

 -------------
 2.高版本
  1)寫一個Fragment類 ---繼承Fragment  (android.app.Fragment)
  至少要重寫onCreateView();----建立一個檢視
  2)將Fragment新增到佈局裡面
  <fragment
     android:name="myfragment的全類名"
  //或者使用class="com.jky.fragment.MyFragment"
  />
 ------------
 3.動態新增
  <FramLayout 幀佈局
  1)使用FragmentManager
  2)事務tran = fm.beginTransaction();
  tran.add()
  tran.replace();
  tran.remove();
  tran.hide();
  tran.show();
  tran.commit();


4.平板設計

注:每個 fragment 都需要提供一個ID(也可以是tag),系統在 activity 重新建立時用它來恢復 fragment,
也可以用它來操作 fragment 進行其它的事物,比如刪除它。

5.fragment的生命週期
1)
2) 注意事項:
fragment生命週期是由Activity控制的。
a.不要在onCreateView裡面去操作Activity的元素(比如回撥Activity方法來操作它的介面);
因為這時候Activity還沒有建立好,應該在onActivityCreated裡面做;
b.加事務回退棧,fragment被replace或者remove的時候不會被銷燬(停在了onDestroyView),
當回來的時候fragment又會重新onCreateView.
因此這就需要我們在操作的時候注意,如果你replace或remove後加入回退棧,要注意儲存資料。
那麼如何儲存資料呢?
方法1:由於不會destroy,所以可以儲存到fragment的全域性變數裡面。
方法2:像EditText可以不用這麼麻煩,只要給其新增ID,系統會自動還原裡面的資料
方法3:既然fragment中的變數都會被儲存,那我們直接將Fragment的檢視直接儲存到變數中,
在系統在利用onCreateView()建立檢視的時候,我們直接返回儲存的檢視。
 1、建立一個變數,儲存Fragment的檢視:
 private View rootView;
` 2、然後來看onCreateView的實現
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
     return getPersistentView(inflater, container, savedInstanceState, R.layout.fragment1);
 }
 
 public View getPersistentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState, int layout) {
     if (rootView == null) {
  // Inflate the layout for this fragment
  rootView = inflater.inflate(layout, container,false);
     } else {
  ((ViewGroup) rootView.getParent()).removeView(rootView);
     }
     return rootView;
 }
 注意:onCreateView()中返回的檢視是要新增到ViewTree中去的。
 而這裡的rootView檢視在上次已經新增到裡面去了,
 一個檢視例項不能被add兩次,不然就會被下面這個錯誤!
 所以,我們針對這種情況,如果rootView已經存在於ViewTree中的時候,要先從ViewTree中移除。


c.hide和多個add方法,不會對當前fragment生命週期造成影響。
如何當一個fragment不在前臺顯示的時候 怎麼處理資源釋放等問題?
在commit後自己來呼叫fragment裡面的方法手動適當處理一些資源問題。

3)如何儲存資料?


6.回退棧
  FragmentTransaction ft = fm.beginTransaction();
  AFragment f = new AFragment();
  ft.add(R.id.fl, f,"afragment");
  ft.addToBackStack("stack1");
  ft.commit();

  fm.popBackStack();相當於返回鍵




fragment注意事項


     1不要在onCreateView裡面去操作Activity的元素(比如回撥Activity方法來操作它的介面)


因為這時候Activity還沒有建立好應該在onActivityCreated裡面做


 


     2沒有加回退棧之前我們使用replace方法去替換fragment的時候那麼之前的fragment會被殺死生命週期執行完。———-當我們新增回退棧的時候我們使用replace方法替換之前的fragment,那麼之前的fragment不會被殺死,這個時候只會呼叫(onPause  ——> onStop—>onDestoryView,但是之前被替換了的fragment身上的view會被幹掉


 


     3)當我們使用add fragment的時候,我們不新增回退棧,這個時候我們的fragment沒有顯示在前臺的時候,這個時候framgent的生命週期方法是不會改變的。新增回退棧同上。當我們點選返回鍵的時候,fragment才會被銷燬掉。


 


     4我們的呼叫show fragmenthide  fragment我們的生命週期方法都是不會發生改變。


 


     5remove fragment的時候我們的生命週期方法也會發生改變 


      6)當我們啟動新的activity的時候,我們的fragment的生命週期也會發生改變(為什麼?因為我們的activity的生命週期發生了改變,所以我們的fragment的生命週期也隨之發生變化)


 


 


     7)解決fragment裡面我們的view被銷燬問題?(呼叫了onDestoryView


     如果你replaceremove後加入回退棧,要注意儲存資料。


那麼如何儲存資料呢?


         7.1)儲存控制元件


         7.2)儲存rootview


         7.3)儲存資料(因為有時候我們的資料他是一個model)


         7.4)設定id


整理自教程