Android Fragment生命周期

本文详细解析了Android中Fragment的生命周期,包括静态添加与动态添加时的不同表现,并探讨了使用addToBackStack方法对Fragment生命周期的影响。
部署运行你感兴趣的模型镜像

在Android 3.0中,Fragment作为一个重要的组件,被添加进来,这个类在  android.app.Fragment; 中,可以直接继承Fragment 创建一个Fragment类,

当然Fragment也是可以在低版本中兼容,在android-support-v4.jar中包含一个FragmentActivity. 可以直接继承FragmentActivity来创建一个Fragment类。

Fragment主要用于平板中,例如:左边显示列表项目,右边显示明细项目,当用户点击每一个条目的时候,右边的Fragment就直接显示用户点击项的明细。

如下图所示:

Fragment的生命周期有:

onAttach();   onCreat();    onCreateView();   onViewCreated(); onActivityCreated();  onStart(); onResume();  onPause();  onStop();  onDestroyView();  onDestroy(); onDetach();

下面请看安卓的官方文档图片:

Fragment的生命周期和Activity的生命周期是有很大关系的.  在含有Fragment 的 Activity的生命周期的变化中,包含着Fragment生命周期的变化

下面请看Android官方文档的Activity与Fragment的生命周期的比较:

当Fragment以静态的方式,即通过在布局文件中以其它控件的方式设置时,它的生命周期随所在Activity的生命周期而发生变化。此时其生命周期的方法调用过程是这样的

1、当Fragment所在的布局页面首次出现的时候, Fragment的生命周期是这样调用的:

2、当手机屏幕关闭或者手机屏幕变暗时,Fragment的生命周期是这样调用的:

3、当进行完上面 2 的操作。再对手机屏幕打开,或者手机变亮的时候,调用顺序是:

4、当对当前的Fragment所在的屏幕按下返回键时,调用顺序是:

 

但是,当使用FragmentManager管理Fragment并且涉及到addToBackStack的时候,那么它的生命周期就会变得更加复杂一点。

下面就来探讨一下这个问题:

先定义FragA.java文件和FragB.java文件 如下:

package com.example.my;

import java.util.jar.Attributes.Name;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragA extends Fragment {
	public static String  TAG = FragA.class.getSimpleName();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i(TAG, "onCreate");
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		   Log.i(TAG, "onActivityCreated");
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.i(TAG, "onCreateView");
		return super.onCreateView(inflater, container, savedInstanceState);
	}
	
	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		 Log.i(TAG, "onAttach");
	}
	@Override
	public void onDestroy() {
		Log.i(TAG, "onDestory");
		super.onDestroy();
	}
	@Override
	public void onDetach() {
		Log.i(TAG, "onDetch");
		super.onDetach();
	}
	@Override
	public void onPause() {
		Log.i(TAG, "onPause");
		super.onPause();
	}
	@Override
	public void onDestroyView() {
		super.onDestroyView();
		Log.i(TAG, "onDestroyView");
	}
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		Log.i(TAG, "onViewCreated");
	}
	@Override
	public void onStart() {
		super.onStart();
		Log.i(TAG, "onStart");
	}

}

 FragB.java文件:

package com.example.my;

import java.util.jar.Attributes.Name;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragB extends Fragment {
	public static String  TAG = FragB.class.getSimpleName();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i(TAG, "onCreate");
	}
	
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		   Log.i(TAG, "onActivityCreated");
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.i(TAG, "onCreateView");
		return super.onCreateView(inflater, container, savedInstanceState);
	}
	
	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		 Log.i(TAG, "onAttach");
	}
	@Override
	public void onDestroy() {
		Log.i(TAG, "onDestory");
		super.onDestroy();
	}
	@Override
	public void onDetach() {
		Log.i(TAG, "onDetch");
		super.onDetach();
	}
	@Override
	public void onPause() {
		Log.i(TAG, "onPause");
		super.onPause();
	}
	@Override
	public void onDestroyView() {
		super.onDestroyView();
		Log.i(TAG, "onDestroyView");
	}
	@Override
	public void onViewCreated(View view, Bundle savedInstanceState) {
		super.onViewCreated(view, savedInstanceState);
		Log.i(TAG, "onViewCreated");
	}
	@Override
	public void onStart() {
		super.onStart();
		Log.i(TAG, "onStart");
	}

}


1、当以下面的方式添加FragA时:

 	FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 	fragA = new FragA();
	fragmentTransaction.replace(R.id.frag_container, fragA, null);
	fragmentTransaction.commit();

它的生命周期展示方式是同在布局文件中静态设置的表现形式是一样的。在这就不多说了。

2、当我们以下面的方式和展示FragA 并且没有addToBackStack时。

@Override
    public void onClick(View v) {
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.button1:
                if (fragA == null) {
                    fragA = new FragA();
                    fragmentTransaction.replace(R.id.frag_container, fragA, fragNames[0]);
//                    fragmentTransaction.addToBackStack(fragNames[0]);
                } else {
                    Fragment fragment = fragmentManager.findFragmentByTag(fragNames[0]);
                    fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[0]);
                }
                break;
            case R.id.button2:
                if (fragB == null) {
                    fragB = new FragB();
                    fragmentTransaction.replace(R.id.frag_container, fragB, fragNames[1]);
//                    fragmentTransaction.addToBackStack(fragNames[1]);
                } else {
                    Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
                    fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);<pre class="java" name="code">   }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();
    }

FragA生命周期调用顺序是:

如果再点击另外一个按钮,将FragB展示出来,请看下面的FragA和FragB的生命周期调用:

我们从这里可以看到。FragA调用顺序为 onPause() , onStop(), onDestoryView(), onDetach() ,这说明, FragA已经被FragmentManager处理掉了,取而代之的是FragB的展现,如果我们也按下返回键按钮,那么FragB的生命周期也是一样的调用onPause() , onStop(), onDestoryView(), onDetach()。这个说明,在添加Fragment时如果没有调用addToBackStack()方式的话,当FragmentManager要更换Fragment的时候,是不会保存要被更换的Fragment的状态的。

3、下面我们在替换Fragment的时候,添加addToBackStack(),那么它的生命周期会是什么样的呢?如下图的:

由此看出,调用addToBackStack()和没调用是有区别的。 当通过按钮,使FragB来替换FragA的时候,此时FragB和FragA的生命周期会做出什么样的变化呢?请看下面的图片:

所以可以看出,FragA生命周期方法只是调用到了onDestroyView,而onDestroy和onDetach则没有被调用,这说明FragA的界面已经被销毁了,但是FragmentManager并没有完全销毁FragA,FragA依然有状态保存在FragmentManager里面。

然后再点击按钮A,使用FragA来替换当前显示的FragB,此时FragA和FragB的生命周期方法调用顺序为:

可以看到,FragB的生命方法调用顺序是跟FragB替换FragA时FragA的调用顺序一致的,作用就是只销毁了视图,但是依然保留了Fragment的状态。而此时FragA的调用则值得注意,此时FragA直接从onCreateView调起,也就是说只是重新创建了视图,而依然使用上次被替换时的Fragment状态。

OK,说到此时,是否对Fragment的生命周期方法调用在是否addToBackStack时不同有所更加深入的了解了呢?

好吧,最后一个问题。是关于Fragment在FragmentManager管理时,show和hide时的生命周期方法调用。

此时的调用实现方式为:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.button1:
                hideAllFrags(fragmentTransaction);
                if (fragA == null) {
                    fragA = new FragA();
                    fragmentTransaction.add(R.id.frag_container, fragA, fragNames[0]);
                    fragmentTransaction.addToBackStack(fragNames[0]);
                } else {
                    fragmentTransaction.show(fragA);
                }
                break;
            case R.id.button2:
                hideAllFrags(fragmentTransaction);
                if (fragB == null) {
                    fragB = new FragB();
                    fragmentTransaction.add(R.id.frag_container, fragB, fragNames[1]);
                    fragmentTransaction.addToBackStack(fragNames[1]);
                } else {
                    fragmentTransaction.show(fragB);
                }
                break;
            default:
                break;
        }
fragmentTransaction.commit();

细心的话可以发现,在展示Fragment时,我们使用了方法add而非上面用的replace。而且直接addToBackStack。其实这也可以理解,你想,FragmentManager在show或者hide时,肯定是已经存在的,或者如果没有的话,需要添加进来Fragment。这便是在show和hide时,需要注意的地方,即使用add和addToBackStack方法。

在点击按钮A时,FragA的调用顺序为:

可以看出没有什么不同于以上所言的部分。然后,点击按钮B时,FragA和FragB的调用顺序为:

可以看出,FragA并没有调用生命周期方法,这说明是展示FragB时,FragA的生命周期并没有发生变化。而FragB的生命周期与初次点击按钮A时FragA的生命周期方法相同。

然后再继续点击按钮A和B,此时打印出来的log为:

这说明在FragA和FragB添加进BackStack之后无论如何地show或者hide,它们的生命周期不再发生变化。

而当屏幕上锁或变暗,然后再解锁或者变亮时,FragA和FragB的生命周期方法调用顺序为:

可以看得出来,两个Fragment都调用了onPause, onStop, onStart, onResume。而且FragA的调用要在FragB之前,这说明跟他们添加进BackStack的顺序有关。

 

本文参考了一些经典资料而出,有不足之处还望谅解,指正。


 

 

 

您可能感兴趣的与本文相关的镜像

Facefusion

Facefusion

AI应用

FaceFusion是全新一代AI换脸工具,无需安装,一键运行,可以完成去遮挡,高清化,卡通脸一键替换,并且Nvidia/AMD等显卡全平台支持

### Android Fragment 生命周期详解 Fragment生命周期与 Activity 密切相关,其状态由宿主 Activity 的生命周期直接控制。以下是 Fragment 的主要生命周期方法及其作用: #### 1. `onAttach(Context context)` - 当 Fragment 与 Activity 建立关联时调用。 - 此时,Fragment 尚未初始化,无法访问视图或上下文资源[^2]。 #### 2. `onCreate(Bundle savedInstanceState)` - 初始化 Fragment 的状态。 - 可以在此方法中执行一些非 UI 相关的初始化操作,例如设置数据源或恢复保存的状态[^2]。 #### 3. `onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)` - 创建并返回 Fragment 的视图。 - 使用 `LayoutInflater` 加载布局文件,并将生成的视图返回给系统[^4]。 ```java @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_example, container, false); } ``` #### 4. `onViewCreated(View view, Bundle savedInstanceState)` - 在视图创建完成后调用。 - 此时可以安全地访问视图组件并进行初始化[^3]。 ```java @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); TextView textView = view.findViewById(R.id.textView); textView.setText("Hello Fragment!"); } ``` #### 5. `onActivityCreated(Bundle savedInstanceState)` - 当宿主 Activity 的 `onCreate()` 方法执行完毕后调用。 - 此时可以访问 Activity 的资源和视图[^2]。 #### 6. `onStart()` - Fragment 开始对用户可见时调用。 - 此时视图已准备就绪,但可能尚未完全显示在屏幕上[^3]。 #### 7. `onResume()` - Fragment 完全可见并与用户交互时调用。 - 这是 Fragment 的前台状态[^2]。 #### 8. `onPause()` - Fragment 即将失去焦点但仍部分可见时调用。 - 可用于保存临时数据或释放轻量级资源[^2]。 #### 9. `onStop()` - Fragment 对用户完全不可见时调用。 - 可用于释放资源或停止后台任务。 #### 10. `onDestroyView()` - Fragment 的视图被移除时调用。 - 此时应清理与视图相关的引用[^3]。 #### 11. `onDestroy()` - Fragment 被销毁时调用。 - 可用于释放所有资源[^2]。 #### 12. `onDetach()` - Fragment 与 Activity 解除关联时调用。 - 此时 Fragment 不再属于任何 Activity[^2]。 --- ### 视图可见性与 Fragment 生命周期的关系 视图的可见性不仅取决于自身的 `setVisibility()` 方法,还受到 Fragment 生命周期的影响。以下是关键点: #### 1. `onStart()` 和 `onResume()` - 在 `onStart()` 中,Fragment 的视图开始对用户可见,但可能尚未完全显示在屏幕上[^3]。 - 在 `onResume()` 中,Fragment 完全可见并与用户交互[^2]。 #### 2. `UserVisibleHint` - `UserVisibleHint` 是一个布尔值,表示 Fragment 是否对用户可见。 - 即使 Fragment 的视图已创建,如果 `UserVisibleHint` 为 `false`,视图也不会对用户可见[^4]。 ```java @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { // 视图对用户可见 } else { // 视图对用户不可见 } } ``` #### 3. 屏幕旋转与配置变更 - 当设备发生配置变更(如屏幕旋转)时,Activity 通常会被重新创建,导致 Fragment 的视图重新绘制[^1]。 - 开发者可以通过 `onSaveInstanceState()` 保存状态并在 `onRestoreInstanceState()` 中恢复。 --- ### 示例代码 以下是一个完整的 Fragment 示例,展示生命周期方法与视图可见性的结合: ```java public class ExampleFragment extends Fragment { private TextView textView; @Override public void onAttach(Context context) { super.onAttach(context); // Fragment 与 Activity 关联 } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化非 UI 数据 } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_example, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); textView = view.findViewById(R.id.textView); textView.setVisibility(View.GONE); // 初始状态下隐藏视图 } @Override public void onStart() { super.onStart(); textView.setVisibility(View.VISIBLE); // 在 onStart() 中使视图可见 } @Override public void onStop() { super.onStop(); textView.setVisibility(View.GONE); // 在 onStop() 中隐藏视图 } @Override public void onDestroyView() { super.onDestroyView(); textView = null; // 清理视图引用 } } ``` --- ### 总结 Fragment生命周期与 Activity 紧密相关,其状态受宿主 Activity 的生命周期直接影响。视图的可见性不仅取决于自身的 `setVisibility()` 方法,还受到 Fragment 生命周期方法(如 `onStart()` 和 `onResume()`)以及 `UserVisibleHint` 的影响。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值