(轉) onCreate()和onCreateView()淺談


onInflate()和onAttach()

Fragment可有一個view hierarchy,以之與用戶互動。這個view層級可以根據XML布局文件被創建(inflated)或通過代碼創建。view層級需要與activity關聯,才能被用戶看見。Fragment的最初的兩個生命周期為onInflate和onAttach。

/* 左邊fragment是list,和ListActivity一樣,繼承ListFragment */
public class TitleFragment extends ListFragment{
    private FragmentBasicTest myActivity = null; 
    private int mCurCheckPosition = 0;  
     
    …... 略 …… 

    @Override //【2】在fragment與activity關聯后調用onAttach()。由於右邊fragment的具體實現在activity的showDetails()中實現,需要獲取activity的對象。 當然也可以直接用getActivity()獲取。
    public void onAttach(Activity activity) {  
        showInfo("onAttach() is called. activity is " + activity); 
        showInfo("   getActivity() : " + getActivity());

        super.onAttach(activity);
        myActivity = (FragmentBasicTest)activity; 
    }     

    @Override//【1】首先調用:在Activity調用setContentView()時,xml中有<fragment>時被調用。bundle存貯的是fragment的狀態,並非初始化的值。一般而言,此時太早,還沒有和activity關聯,一般很少需要在此進行處理,除非我們需要處理fragment的屬性或參數。在API的reference中,Fragment的主要lifecycle甚至沒有將onInflate()列入,因此在實際編程中,會較少用到。
    public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 
        showInfo("onInfalte() is called");
        showInfo("   activity : " + activity);
        showInfo("   getActivity() : " + getActivity()); //Fragment尚為關聯activity
        showInfo("   attribute是fragment的屬相,例如R.id.titles =  " + R.id.titles); 
        for(int i = 0 ; i< attrs.getAttributeCount() ; i ++){ 
            showInfo("    attribute " + i + " :" + attrs.getAttributeName(i) + " = " + attrs.getAttributeValue(i));
        } 
        showInfo("   bundle : " + savedInstanceState);
       super.onInflate(activity, attrs, savedInstanceState);
    } 

    private void showInfo(String s){ 
        Log.d("TitleFragment",s); 
    }     
}

我們看看運行的logcat顯示。我們可以看出,在activity調用setContentView時,先調用Flagment中的onflate(),然后調用onAttach()。在onInfalte()中可以讀取到我們在xml文件中<fragment… >設置的屬性。在后面實現右邊的fragment中,由於布局文件中<fragment …>中並沒有指定class屬性,而是在代碼中實現,故沒有onInflate()狀態。

與activity的關聯:看到onInfalte()和onAttach()都可以獲得activity對象,但是如果采用getActivity()來獲取,則發現onInfalte()的階段對處理UI太早,都不能關聯到activity。

參數:在整個生命周期,可以通過getArguments()來獲取參數,但是不能在與activity關聯后進行setArgments(),只能在初始化極早的階段,例如構造函數和onInflate()。

onCreate()和onCreateView()

@Override //【3】在創建fragment中進行初始化時調用。注意此處的bundle參數,是存儲fragment的狀態。如果我們要為fragment啟動一個后台線程,可以考慮將代碼放於此處。 
public void onCreate(Bundle savedInstanceState) {  
   showInfo("onCreate() is called. ");
    super.onCreate(savedInstanceState);


@Override //【4】創建fragment,並返回fragment的view層次結構,用於對UI的設計。本例繼承了ListFragment實現,由其生成ListView,它的資源ID是android.R.id.list1,或者可以通過getListView()來獲取。我們在此不需要在進行特別的處理,僅用於跟蹤生命周期。
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    showInfo("onCreateView() is called. ");
    return super.onCreateView(inflater, container, savedInstanceState);

onCreate()和onCreateView()都是在activity調用setContentView()時被調用。也就是activity上未完成onCreate(),因此不應該在此加入與activity的view相關的代碼。而后面的生命周期這是在activity完成onCreate()之后調用的。

onActivityCreated()

onActivityCreated顧名思義,是在activity完成onCreate()后被調用。我們可以在此處理activity的其他UI操作,而其他的fragment已經與activity關聯,我們可以進行相互間處理。這也是用戶看到UI界面之前的最后一個狀態,對於從saved狀態中重新創建activity及fragment來講是重要狀態。

回想一下,在ListActivity中是在setContentView()后面進行Adapter的設置,因為setContentView已經提供了view層級,因此在fragment中具體設置list也放在fragment的onCreateView()之后的生命周期onActivityCreated()中執行。

   @Override //【5】onActivityCreated()在activity完成onCreate()后執行,在此可以加入UI設計(onCreateView())之后,UI被用戶看到之前的代碼。 
    public void onActivityCreated(Bundle savedInstanceState) {  
        showInfo("onActivityCreated() is called.");
        super.onActivityCreated(savedInstanceState); 
       // 1)通過Adapter進行view和data的關聯   
        setListAdapter
(new ArrayAdapter<String>(getActivity(),   //注意:在ListFragment中要直接和ListView(通過id或者getListView()獲取)關聯,而要用setListAdapter()
                android.R.layout.simple_list_item_1, 
                BooksInfo.TITLES)); 
        ListView lv = getListView(); 
        lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
        lv.setSelection(mCurCheckPosition); 
        //2)根據書名設置右邊framgent UI。 
        myActivity.showDetails(mCurCheckPosition); 
    }

onStart()、onResume()、onPause()和onStop()

這幾個狀態和activty的相應狀體相似,對應為可視,可互動,不可互動和不可視。和activity的生命周期圖相對比,從不可視的后台回復到可視的前台的過程是onStop()—>onRestart()—>onStart()。而fragment為onStop()—>onStart()。

onDestroyView()、onDestroy和onDetach()

當fragment允許與view相關的資源釋放時調用onDestroyView(),清空通過onCreateView()所返回的view。接着,onDestroy()進行最后fragment狀態的清空。最后調用onDetach(),刪除與activity的關聯()。

與用戶互動處理

@Override //當用戶點擊書名,在右邊fragment中顯示相關的內容。在ListFragment中可以直接通過回調函數onListItemClick來實現。
public void onListItemClick(ListView l, View v, int position, long id) { 
    mCurCheckPosition = position; 
    myActivity.showDetails(mCurCheckPosition); 

本博文涉及的例子代碼,可以在Pro Android學習:Fragment中下載。


免責聲明!

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



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