Activity與Fragment


  Fragment是Android honeycomb 3.0新增的概念,Fragment名為碎片不過卻和Activity十分相似。

  Fragment是用來描述一些行為或一部分用戶界面在一個Activity中,

(1)你可以合並多個fragment在一個單獨的activity中建立多個UI面板,

(2)同時重用fragment在多個activity中。

  你可以認為fragment作為一個activity中的一節模塊 ,fragment有自己的生命周期,接收自己的輸入事件,你可以添加或移除從運行中的activity。

  從中可以看出:一個fragment必須總是嵌入在一個activity中,同時fragment的生命周期 受 activity而影響。當activity 暫停,那么所有在這個activity的fragments將被destroy釋放。

 

處理Fragment的生命周期

宿主activity的聲明周期直接影響到fragment的生命周期。

 Activity的生命周期:

Fragment生命周期:

  創建一個fragment你必須創建一個Fragment的子類或存在的子類,比如類似下面的代碼

public static class AndroidFragment  extends Fragment {
    @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) { 
                return inflater.inflate(R.layout.android_fragment, container,  false);
    }
}

onAttach()

  當fragment和activity被關聯時調用。

onCreate()
當fragment創建時被調用,你應該初始化一些實用的組件,比如在fragment暫停或停止時需要恢復的

onCreateView()
當系統調用fragment在首次繪制用戶界面時,如果畫一個UI在你的fragment你必須返回一個View當然了你可以返回null代表這個fragment沒有UI.

onActivityCreated()

  當activity的onCreate()方法返回時調用。

  onResumed()

  在running狀態下的可見狀態。

  onPaused()

  另一個activity在前景運行,並且享有焦點,但是這個fragment所在的activity仍然可見(前景activity部分遮擋或者是半透明的)。

  onStop()

  fragment不可見。可能是因為宿主activity處於stopped狀態,或者fragment被remove掉,然后加在了back stack中。

  一個處於stopped狀態的activity還是存活狀態的,所有的狀態和成員信息會被系統保持。但是,它不再被用戶可見,並且如果宿主activity被kill掉,它也會被kill掉。

onDestroyView()

  當fragment的UI被移除的時候調用。

onDetach()

  當fragment和activity去關聯時調用。

 

數據存儲和恢復

  和Activity類似,可以用Bundle類對象保存fragment的狀態,當activity的進程被kill之后,需要重建activity時,可以用於恢復fragment的狀態。

  存儲時利用onSaveInstanceState()回調函數,恢復時是在 onCreate()onCreateView(), 或者onActivityCreated()里。

 

兩者的區別

1.fragment顯得更加靈活。可以直接在XML文件中添加<fragment/>,Activity則不能

eg:

<fragment

Android:id="@+id/left_fragment"

Android:name="com.example.fragmenttest.LeftFragment"

…/>

2.可以在一個界面上靈活的替換一部分頁面,activity不可以,做不到。

  替換的時候注意要將這個fragment放在返回棧上。

3.fragment和Activity之間的通信:(也就是控件的相互操控)

  fragment控制fragment:得到一個Activity,然后通過這個Activity的getFragmentManager()獲得該Fragment的實例。

  fragment控制Activity:這個很簡單。每個Fragment都有getActivity()得到一個Activity的實例:

View listView = getActivity().findViewById(R.id.list);PS:在當前activity和fragment已經進行關聯的情況下否則返回null。

  Activity控制fragment:activity也可以獲得一個fragment的引用,從而調用fragment中的方法:

xxxFragment xxx=getFragmentManager().findFragmentById();

  Activity控制Activity:這個顯然是通過Intent活動之間的通信完成。別忘了在被打開的活動中創建Intent和得到Intent一起進行,寫個靜態的actionStart()。

4.fragment和Activity中控件的加載

  Fragment的載入是通過OnCreateView的時候通過inflater.inflate()加載布局,然后通過修改main.xml,在main.xml上增加注冊fragment標簽,然后通過android:name來載入你已經通過inflater加載的隱藏布局。

  有幾個關鍵點:fragment是通過inflater加載View然后在main.xml中注冊得到的。當然如果你可以在fragment中得到View那就可以通過View.findViewId()來操控fragment上的具體控件。

5.動態加載不同的fragment:

  首先,監聽你的按鈕。

1.創建待加載fragment的實例

2.得到FragmentManager,在actibity中可以直接調用getFragmentManager()方法獲得。

3.調用Manager的BeginTansation()

4.用replace()改變不同的Fragment

5.commit事務。

6.Back Stack

  activity和fragment生命周期最重要的不同之處是它們如何存儲在各自的back stack中。

  Activity停止時,是存在一個由系統維護的back stack中,但是當fragment停止(被remove)時,需要程序員顯式地調用addToBackStack() ,並且fragment是存在一個由宿主activity掌管的back stack中。

創建事件回調

  些情況下,可能需要fragment和activity共享事件,一個比較好的做法是在fragment里面定義一個回調接口,然后要求宿主activity實現它。

當activity通過這個接口接收到一個回調,它可以同布局中的其他fragment分享這個信息。

  例如,一個新聞顯示應用在一個activity中有兩個fragment,一個fragment A顯示文章題目的列表,一個fragment B顯示文章。

  所以當一個文章被選擇的時候,fragment A必須通知activity,然后activity通知fragment B,讓它顯示這篇文章。

  這個情況下,在fragment A中聲明一個這樣的接口OnArticleSelectedListener:

public static class FragmentA extends ListFragment {
...
// Container Activity must implement this interface
  public interface OnArticleSelectedListener {
  public void onArticleSelected(Uri articleUri);
    }
  ...
}

  之后包含這個fragment的activity實現這個OnArticleSelectedListener接口,用覆寫的onArticleSelected()方法將fragment A中發生的事通知fragment B。

  為了確保宿主activity實現這個接口,fragment A的onAttach() 方法(這個方法在fragment 被加入到activity中時由系統調用)中通過將傳入的activity強制類型轉換,實例化一個OnArticleSelectedListener對象:

public static class FragmentA extends ListFragment {
  OnArticleSelectedListener mListener;
...
  @Override
  public void onAttach(Activity activity) {
  super.onAttach(activity);
    try {
    mListener = (OnArticleSelectedListener) activity;
      } catch (ClassCastException e) {
      throw new ClassCastException(activity.toString() + " must implement     OnArticleSelectedListener");
      }
    }
  ...
}

  如果activity沒有實現這個接口,fragment將會拋出ClassCastException異常,如果成功了,mListener將會是activity實現OnArticleSelectedListener接口的一個引用,所以通過調用OnArticleSelectedListener接口的方法,fragment A可以和activity共享事件。

  比如,如果fragment A是ListFragment的子類,每一次用戶點擊一個列表項目,系統調用fragment中的onListItemClick() 方法,在這個方法中可以調用onArticleSelected()方法與activity共享事件。

public static class FragmentA extends ListFragment {
  OnArticleSelectedListener mListener;
  ...
  @Override
  public void onListItemClick(ListView l, View v, int position, long id) {
  // Append the clicked item's row ID with the content provider Uri
    Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
  // Send the event and Uri to the host activity
    mListener.onArticleSelected(noteUri);
      }
    ...
  }

 

參考資料

  API Guides: Fragments

  http://developer.android.com/guide/components/fragments.html

  http://www.cnblogs.com/mengdd/archive/2013/01/11/2856374.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM