Fragment生命周期以及使用時的小問題
前言-
昨天在寫UI的時候用到了FRAGMENT,發現自己對此還不是非常了解,借此機會記錄一下
Fragment的生命周期-
官方生命周期圖:
Fragment每個生命周期方法的意義、作用-
onViewStateRestored(Bundle):告訴片段,它的視圖層次結構的所有保存狀態都已恢復。
setUserVisibleHint():設置Fragment可見或者不可見時會調用此方法。在該方法裏面可以通過調用getUserVisibleHint()獲得Fragment的狀態是可見還是不可見的,如果可見則進行懶加載操作。onAttach():執行該方法時,Fragment與Activity已經完成綁定,該方法有一個Activity類型的參數,代表綁定的Activity,這時候你可以執行諸如mActivity = activity的操作。
onCreate():初始化Fragment。可通過參數savedInstanceState獲取之前保存的值。
onCreateView():初始化Fragment的布局。加載布局和findViewById的操作通常在此函數內完成,但是不建議執行耗時的操作,比如讀取數據庫數據列表。
onActivityCreated():執行該方法時,與Fragment綁定的Activity的onCreate方法已經執行完成並返回,在該方法內可以進行與Activity交互的UI操作,所以在該方法之前Activity的onCreate方法並未執行完成,如果提前進行交互操作,會引發空指針異常。
onStart
onResume():執行該方法時,Fragment處於活動狀態,用戶可與之交互。
onPause():執行該方法時,Fragment處於暫停狀態,但依然可見,用戶不能與之交互。
onSaveInstanceState():保存當前Fragment的狀態。該方法會自動保存Fragment的狀態,比如EditText鍵入的文本,即使Fragment被回收又重新創建,一樣能恢復EditText之前鍵入的文本。
onStop():執行該方法時,Fragment完全不可見。
onDestroyView():銷毀與Fragment有關的視圖,但未與Activity解除綁定,依然可以通過onCreateView方法重新創建視圖。通常在ViewPager+Fragment的方式下會調用此方法。
onDestroy():銷毀Fragment。通常按Back鍵退出或者Fragment被回收時調用此方法。
onDetach():解除與Activity的綁定。在onDestroy方法之後調用。
Fragment生命周期執行流程-
-
Fragment創建
setUserVisibleHint()->onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume();Fragment變為不可見狀態(鎖屏、回到桌面、被Activity完全覆蓋):onPause()->onSaveInstanceState()->onStop();
-
Fragment變為部分可見狀態(打開Dialog樣式的Activity)
onPause()->onSaveInstanceState();
-
Fragment由不可見變為活動狀態
onStart()->OnResume();
-
Fragment由部分可見變為活動狀態
onResume();
-
退出應用
onPause()->onStop()->onDestroyView()->onDestroy()->onDetach()(註意退出不會調用onSaveInstanceState方法,因為是人為退出,沒有必要再保存數據);
-
Fragment被回收又重新創建:
被回收執行onPause()->onSaveInstanceState()->onStop()->onDestroyView()->onDestroy()->onDetach(),
重新創建執行onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->setUserVisibleHint();
-
橫豎屏切換-
與Fragment被回收又重新創建一樣。
摘自法捷耶夫大佬的文章https://www.cnblogs.com/fajieyefu/p/6092465.html
實戰中遇到的一些小問題-
Fragment中獲取上下文Context對象
getActivity(); //獲取包含該fragment的活動(activity)的上下文
通過上面的生命周期我們知道fragment在OnAttach後才會獲取Activity,所以這個方法需要寫在onAttach()或者在其以後生命周期方法中
@Override public void onAttach(Activity activity) { super.onAttach(activity); context=this.getActivity(); }
getContext(); //獲取該fragment上下文 只查看當前運行的活動的上下文。(Fragment是嵌在Activity的話,感覺這個和Activity的context是一樣的)
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view=inflater.inflate(R.layout.fragment_liebie,container,false); context=view.getContext(); }
getApplicationContext() ; //生命周期是整個應用,應用摧毀它才摧毀。而Activity.this的context 拿到的是當前Activity的Context,而getApplicationContext()拿到的是Application的Context。
1.this.getActivity()
- 優點:直接調用就能獲取
- 缺點:
Fragment
很容易被銷毀,調用getActivity()
方法會報空指針錯誤(註意:並不是getActivity()
返回值為null
,而是this.getActivity()
中的this
,也就是Fragment
自己是null
,因為它已經被銷毀了)
2.獲取Application對象
- 優點:不會遇到類似
this.getActivity()
的空指針問題 - 缺點:某些情況下的
Context
必須是Activity
,特別是實例化Dialog
等需要依附於一個Activity
的可視化的對象時傳參必須是Activity
對象(Toast
是Android的一種通知機制,不需要依附於Activity
)
getActivity().getApplicationContext();//通過包含該fragment的活動(activity)獲取整個應用的上下文
getContext().getApplicationContext();//通過該fragment獲取整個應用的上下文Fragment中findViewById
這四種方式效果相同
Fragment中的findViewById
findViewById方法卻只能被用在Activity類中,但是如果想要在fragment中使用的話就需要view了
View view = inflater.inflate(R.layout.view, container, false); //兩種皆可 TextView tx=view.findViewById(R.id.id_view); //TextView tx=getView().findViewById(R.id.id_view);
Fragment生命周期以及使用時的小問題