開始第一章,片段。
爲什麼是片段而不是活動呢?因爲活動的基礎回調和基礎使用很簡單,源碼又很難,而且涉及啓動模式,狀態保存等等,等筆者找到一個能貫穿的平衡點,會單獨開一篇活動專題複習。
安卓深入哪一塊其實都不簡單,所以片段也只講重點,點到爲止。
初次導入片段時需要選擇導哪個包的,有如下兩個選擇
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中都是這樣執行,多動動手總會有收穫。