Android溫故知新之Fragment篇(一) Fragment生命週期

夜深了,又到了擼代碼的時間,其實一直想把以前學的東西總結一下,看看有哪些疏漏和誤解的地方,從這裏開始開一個複習系列,當然對於很多剛學習安卓的同學,這應該是一個入門系列。
開始第一章,片段。

爲什麼是片段而不是活動呢?因爲活動的基礎回調和基礎使用很簡單,源碼又很難,而且涉及啓動模式,狀態保存等等,等筆者找到一個能貫穿的平衡點,會單獨開一篇活動專題複習。

安卓深入哪一塊其實都不簡單,所以片段也只講重點,點到爲止。

初次導入片段時需要選擇導哪個包的,有如下兩個選擇

android.support.v4.app.Fragment
android.app.Fragment;

support.v4.app下的片段具有更好的兼容性,可以兼容到1.6版本,而應用下的片段只支持3.0以上的版本,如果minsdk設置在3.0以上,當然用哪個都可以,如果需要兼容到3.0以下,建議使用V4包下的片段。

劃重點1:support.v4.app下的片段可以兼容到1.6版本,且support.v4.app下的片段和應用下的片段不具有繼承關係,無法進行類型轉換。

筆者以support.v4.app下的片段爲例,正式開始今天的學習。

首先創建MyFragment:

MyFragment.java

public class MyFragment extends Fragment {
    private static final String TAG =“MyFragment--”;
    @Override
    public void onInflate(Context context,AttributeSet attrs,Bundle savedInstanceState){
        super.onInflate(context,attrs,savedInstanceState);
        Log.d(TAG,“onInflate:執行”);
    }

    @Override
    public void onAttach(Context context){
        super.onAttach(context);
        Log.d(TAG,“onAttach:執行”);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: 執行");
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView: 執行");
        View view = inflater.inflate(R.layout.fragment_my,container,false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated: 執行");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: 執行");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: 執行");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: 執行");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: 執行");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "onDestroyView: 執行");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: 執行");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "onDetach: 執行");
    }
}


fragment_my.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width = “match_parent”
        android:layout_height = “match_parent”
        android:text= “fragment”/>
</RelativeLayout>

然後創建承載片段的活性:

MyActivity.java

public MyActivity extends AppCompatActivity {
    private static final String TAG =“MyActivity ++”;
    @Override
    protected onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        Log.d(TAG,"onCreate:執行");
        Log.d(TAG,"setContentView:執行前");
        setContentView(R.layout.activity_my);
        Log.d(TAG,"setContentView:執行後");
    }

    @Override
    protected onStart(){
        super.onStart();
        Log.d(TAG,"onStart:執行");
    }

    @Override
    protected onStop(){
        super.onStop();
        Log.d(TAG,"onStop:執行");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: 執行");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: 執行");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: 執行");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart: 執行");
    }
}

activity_my.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.tustcs.ndktest.MyActivity">
    <fragment
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:id = "@+id/my_fragment"
        class= "com.tustcs.ndktest.MyFragment"/>
</RelativeLayout>

運行程序,啓動時輸出如下

可以發現,onInflate,onAttach,的onCreate,onCreateView,onActivityCreated這四個方法都發生在給活動設置視圖的時候,在onStart,的onResume分別與活動的調用onStart,的onResume對應。

點擊回鍵後,銷燬過程如下


銷燬過程中片段的的onPause,的onStop分別和活動的的onPause,的onStop相對應,onDestroyView,onDestory,onDetach發生在活動的的onDestroy方法中。並且和活性一樣,片段的生命週期方法也是成對出現的,按什麼順序創建就按它的逆序銷燬。

我們又可以搬出那張經典的圖:


沒錯,這裏少了onInflate方法,onInflate只有在通過<片段>標籤添加片段時纔會調用。

public void onInflate(上下文上下文,AttributeSet attrs,Bundle savedInstanceState) 

注意onInflate的第二個參數和第三個參數,熟悉自定義視圖的人對AttrbuteSet一定非常熟悉,這是搜索獲取XML值的關鍵,所以在其方法內,可以讀取到其XML中的屬性值,通過第三個參數可以保存狀態。

通過

public class MyActivity extends AppCompatActivity {
    private static final String TAG = "MyActivity++";
    private MyFragment myFragment;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: 執行");
        super.onCreate(savedInstanceState);

        Log.d(TAG, "setContentView: 執行前");
        setContentView(R.layout.activity_my);
        Log.d(TAG, "setContentView: 執行後");

        myFragment = new MyFragment();
        android.support.v4.app.FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.add(myFragment,"aaa");
        ft.commit();
    }

運行結果如下:

動態添加Fragment不會調用onInflate。


至於爲什麼一張圖就能總結的東西,筆者還是敲了一堆代碼去驗證,或許這就是計算機的學習之路,實踐出真知,就像筆者曾在一本書中介紹說Fragment的onInflate會在Activity的onCreate之前調用,經過親自驗證才發現並不是如此,至少不在所有版本的SDK中都是這樣執行,多動動手總會有收穫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章