Fragment生命周期詳解
1. Fragment概述
Fragment從Android v3.0版本開始引入,大家談什么都能跟Fragment談上關系,做什么都要問下Fragment能實現不。隨著界面布局的復雜化,處理起來也更加的復雜,引入Fragment可以把activity拆分成各個部分。每個Fragment都有它自己的布局和生命周期,方便了開發。
采用fragment而不是activity進行應用的UI管理,可繞開Android系統activity規則的限制。
fragment是一種控制器對象,activity可委派它完成一些任務通常這些任務就是管理用戶界面。受管的用戶界面可以是一整屏或是整屏的一部分。管理用戶界面的fragment又稱為UI fragment。它也有自己產生于布局文件的視圖。fragment視圖包含了用戶可以交互的可視化UI元素。
activity托管fragment,暫時可以把托管理解成activity在其視圖層級里提供一處位置來放置fragment的視圖。fragment本身不具有在屏幕上顯示視圖的能力,因此,只有將它的視圖放置在activity的視圖層級結構中,fragment視圖才能顯示在屏幕上。
使用 Fragment 的好處就是可以把業務邏輯和 UI 封裝在一起,與外部關聯系不大, 其他程序也可以用該組件,從而實現復用最大化。
2. 兩種方式加入Fragment
首先創建 Demo3Fragment 繼承 Fragment 類, 并為其創建xml布局文件
package com.ashzheng.studydemo.demo3;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ashzheng.studydemo.R;
public class Demo3Fragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_demo3, container, false);
return view;
}
}
1. 通過XML標簽
在activity的xml布局文件中添加節點
<fragment
android:id="@+id/demo3_fg"
android:name="com.ashzheng.studydemo.demo3.Demo3Fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
2. 通過代碼動態創建
- 在activity的xml布局文件中添加容器視圖
<FrameLayout android:id="@+id/demo3_layout" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> - 在activity中動態添加fragment
package com.ashzheng.studydemo.demo3; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import com.ashzheng.studydemo.R; public class Demo3Activity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo3); FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.add(R.id.demo3_layout, new Demo3Fragment()); fragmentTransaction.commit(); } }
3. Fragment生命周期
fragment生命周期類似于activity的生命周期。生命周期方法的對應非常重要,因為fragment代表activity在工作,它的狀態應該也反應了activity的狀態。因而,fragment需要對應的生命周期方法來處理activity的工作。
這些方法的作用會在代碼中的注釋給出
Fragment
1. 界面打開
onCreate() 方法執行!
onCreateView() 方法執行!
onActivityCreated() 方法執行!
onStart() 方法執行!
onResume() 方法執行!
2. 按下主屏幕鍵/鎖屏
onPause() 方法執行!
onStop() 方法執行!
3. 重新打開
onStart() 方法執行!
onResume() 方法執行!
4. 按下后退鍵
onPause() 方法執行!
onStop() 方法執行!
onDestroyView() 方法執行!
onDestroy() 方法執行!
onDetach() 方法執行!
Activity
1. 打開應用
onCreate() 方法執行!
onStart() 方法執行!
onResume() 方法執行!
2. 按下主屏幕鍵/鎖屏
onPause() 方法執行!
onStop() 方法執行!
3. 重新打開應用
onRestart() 方法執行!
onStart() 方法執行!
onResume() 方法執行!
4. 按下后退鍵
onPause() 方法執行!
onStop() 方法執行!
onDestroy() 方法執行!
在Activity中加入Fragment,對應的生命周期
1. 打開
Fragment onCreate() 方法執行!
Fragment onCreateView() 方法執行!
Activity onCreate() 方法執行!
Fragment onActivityCreated() 方法執行!
Activity onStart() 方法執行!
Fragment onStart() 方法執行!
Activity onResume() 方法執行!
Fragment onResume() 方法執行!
2. 按下主屏幕鍵/鎖屏
Fragment onPause() 方法執行!
Activity onPause() 方法執行!
Fragment onStop() 方法執行!
Activity onStop() 方法執行!
3. 再次打開
Activity onRestart() 方法執行!
Activity onStart() 方法執行!
Fragment onStart() 方法執行!
Activity onResume() 方法執行!
Fragment onResume() 方法執行!
4. 按下后退鍵
Fragment onPause() 方法執行!
Activity onPause() 方法執行!
Fragment onStop() 方法執行!
Activity onStop() 方法執行!
Fragment onDestroyView() 方法執行!
Fragment onDestroy() 方法執行!
Fragment onDetach() 方法執行!
Activity onDestroy() 方法執行!
可以發現,創建的時候都是activity的方法先執行,停止、銷毀的時候都是fragment的方法先執行。
fragment生命周期與activity生命周期的一個關鍵區別就在于,fragment的生命周期方法是由托管activity而不是操作系統調用的。操作系統無從知曉activity用來管理視圖的fragment。fragment的使用是activity自己內部的事情。可以發現,activity中的生命周期方法都是protected,而fragment的則是public,這就是因為fragment是由activity來管理的,activity需要調用這些個方法。
4.Fragment中的數據保存
和在activity中一樣,fragment也提供了onSaveInstanceState()方法,使用也基本和activity一樣,不同的是,在fragment中,雖然Fragment.onCreate()方法配置了fragment實例,但創建和配置fragment視圖是通過Fragment.onCreateView()方法來完成的,所以可以在Fragment.onCreateView()這個方法中獲取在保存狀態下重建視圖所使用的數據。
實現代碼:
Demo3Fragment
package com.ashzheng.studydemo.demo3;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ashzheng.studydemo.R;
public class Demo3Fragment extends Fragment {
@Override
public void onAttach(Context context) {
//當fragment 第一次與 Activity 產生關聯時調用,以后不再調用
super.onAttach(context);
Log.d("demoinfo", "Fragment onAttach() 方法執行!");
}
@Override
public void onCreate(Bundle savedInstanceState) {
//在 onAttach 執行完后會立刻調用此方法,通常被用于讀取保存的狀態值,獲取或者初始化一些數據,
// 但是該方法不執行,窗口是不會顯示的,因此如果獲取的數據需要訪問網絡,最好新開線程。
super.onCreate(savedInstanceState);
Log.d("demoinfo", "Fragment onCreate() 方法執行!");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//創建 Fragment 中顯示的 view, 其中 inflater 用來裝載布局文件, container 表示 <fragment> 標簽的父標簽對應的 ViewGroup 對象,
// savedInstanceState 可以獲取 Fragment 保存的狀態
Log.d("demoinfo", "Fragment onCreateView() 方法執行!");
if(null != savedInstanceState){
Log.d("demoinfo", "保存了的數據: "+ savedInstanceState.getString("myinfo"));
}else {
Log.d("demoinfo", "沒有保存的數據!");
}
View view = inflater.inflate(R.layout.fragment_demo3, container, false);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
//在 Activity.onCreate() 方法調用后會立刻調用此方法,表示窗口已經初始化完畢,此時可以調用控件了
super.onActivityCreated(savedInstanceState);
Log.d("demoinfo", "Fragment onActivityCreated() 方法執行!");
}
@Override
public void onStart() {
//開始執行與控件相關的邏輯代碼,如按鍵點擊
super.onStart();
Log.d("demoinfo", "Fragment onStart() 方法執行!");
}
@Override
public void onResume() {
//這是 Fragment 從創建到顯示的最后一個回調的方法
super.onResume();
Log.d("demoinfo", "Fragment onResume() 方法執行!");
}
@Override
public void onPause() {
//當發生界面跳轉時,臨時暫停,暫停時間是 500ms,0.5s后直接進入下面的 onStop 方法
super.onPause();
Log.d("demoinfo", "Fragment onPause() 方法執行!");
}
@Override
public void onStop() {
//當該方法返回時, Fragment 將從屏幕上消失
super.onStop();
Log.d("demoinfo", "Fragment onStop() 方法執行!");
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d("demoinfo", "Fragment onSaveInstanceState() 方法執行!");
outState.putString("myinfo", "haha");
}
@Override
public void onDestroyView() {
//當 fragment 狀態被保存,或者從回退棧彈出,該方法被調用
super.onDestroyView();
Log.d("demoinfo", "Fragment onDestroyView() 方法執行!");
}
@Override
public void onDestroy() {
//當 Fragment 不再被使用時,如按返回鍵,就會調用此方法
super.onDestroy();
Log.d("demoinfo", "Fragment onDestroy() 方法執行!");
}
@Override
public void onDetach() {
//Fragment 生命周期的最后一個方法,執行完后將不再與 Activity 關聯,將釋放所有 fragment 對象和資源
super.onDetach();
Log.d("demoinfo", "Fragment onDetach() 方法執行!");
}
}
Demo3Activity
package com.ashzheng.studydemo.demo3;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import com.ashzheng.studydemo.R;
public class Demo3Activity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo3);
Log.d("demoInfo", "Activity onCreate() 方法執行!");
// FragmentManager fragmentManager = getFragmentManager();
// FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// fragmentTransaction.add(R.id.demo3_layout, new Demo3Fragment());
// fragmentTransaction.commit();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("demoInfo", "Activity onDestroy() 方法執行!");
}
@Override
protected void onPause() {
super.onPause();
Log.d("demoInfo", "Activity onPause() 方法執行!");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d("demoInfo", "Activity onRestart() 方法執行!");
}
@Override
protected void onStart() {
super.onStart();
Log.d("demoInfo", "Activity onStart() 方法執行!");
}
@Override
protected void onStop() {
super.onStop();
Log.d("demoInfo", "Activity onStop() 方法執行!");
}
@Override
protected void onResume() {
super.onResume();
Log.d("demoInfo", "Activity onResume() 方法執行!");
}
}
activity_demo3.xml
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.ashzheng.studydemo.demo3.Demo3Activity">
<fragment
android:id="@+id/demo3_fg"
android:name="com.ashzheng.studydemo.demo3.Demo3Fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/demo3_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>

