Fragment生命周期

本文详细解析了Fragment在不同场景下的生命周期变化,包括静态方式、动态添加、使用addToBackStack及show/hide函数时的具体行为。

本文转载于 Fragment生命周期详解,感谢博主的付出,转载到此,也是为了自己的工作学习。大家一起进步

简单来说,Fragment 的生命周期可以用下图来表示:

 1. onAttach(),该方法是用在Fragment和Activity建立关系的时候调用的,它会携带一个参数Context或者Activity(API < 23时)。 
 2. onCreate(),与Activity的onCreate()方法一样,都是对象被创建的时候调用注意,此时Activity并未完成初始化,也就是还没有调用onStart()方法。 
 3. onCreateView(),这个方法就是在要初始化Fragment界面的时候调用的,这个基本上是必须重写的函数,再此函数中加载布局并返回。 
 4. onActivityCreate(),这个方法回调的时候表示Activity已经初始化完了,也就是开始继续执行onStart()等后续方法了。 
 5. onDestroyView(),这个方法是在Fragment所包含的组件被销毁时调用。 
 6. onDetach(),这个方法是在Fragment从Activity删除或者被替换时调用,当执行了onDestroy()方法后会执行此方法。 

这上边有很多生命周期的回调函数与Activity的回调函数名字是一样,他们所完成的功能也基本一致,对其中的一些函数具体说明一下: 

一、使用静态方式时的生命周期:

此时Fragment的生命周期为onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.

1、其中当创建一个Fragment首次展示其布局界面时:

onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态

2、当关闭手机屏幕或者手机屏幕变暗或直接按home键返回桌面时,其生命周期方法调用的顺序是

onPause, onStop

3、当再次对手机屏幕解锁或者手机屏幕变亮时,其生命周期方法调用的顺序:

onStart, onResume

4、当对Fragment按返回键时:

onPause, onStop, onDestroyView, onDestroy, onDetach.


 

二、使用FragmentManager动态的添加Fragment:

这是本博客讲解的重点,因为动态添加涉及到Fragment的切换,所以我们先定义两个Fragment。代码如下:

public class FragOne extends Fragment {
    private static final String TAG = FragOne.class.getSimpleName();
 
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.i(TAG, "onAttach");
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate");
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView");
        return inflater.inflate(R.layout.fragment_test_a, null, false);
    }
 
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.i(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }
 
    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        super.onDestroy();
    }
 
    @Override
    public void onDetach() {
        Log.i(TAG, "onDetach");
        super.onDetach();
    }
 
    @Override
    public void onDestroyView() {
        Log.i(TAG, "onDestroyView");
        super.onDestroyView();
    }
 
    @Override
    public void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }
 
    @Override
    public void onStop() {
        Log.i(TAG, "onStop");
        super.onStop();
    }
 
    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
    }
 
    @Override
    public void onPause() {
        Log.i(TAG, "onPause");
        super.onPause();
    }
 
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "onActivityCreated");
        super.onActivityCreated(savedInstanceState);
    }
}

第二个Fragment

public class FragTwo extends Fragment {
    private static final String TAG = FragTwo.class.getSimpleName();
 
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.i(TAG, "onAttach");
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate");
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView");
        return inflater.inflate(R.layout.fragment_test_b, null, false);
    }
 
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        Log.i(TAG, "onViewCreated");
        super.onViewCreated(view, savedInstanceState);
    }
 
    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy");
        super.onDestroy();
    }
 
    @Override
    public void onDetach() {
        Log.i(TAG, "onDetach");
        super.onDetach();
    }
 
    @Override
    public void onDestroyView() {
        Log.i(TAG, "onDestroyView");
        super.onDestroyView();
    }
 
    @Override
    public void onStart() {
        Log.i(TAG, "onStart");
        super.onStart();
    }
 
    @Override
    public void onStop() {
        Log.i(TAG, "onStop");
        super.onStop();
    }
 
    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        super.onResume();
    }
 
    @Override
    public void onPause() {
        Log.i(TAG, "onPause");
        super.onPause();
    }
 
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "onActivityCreated");
        super.onActivityCreated(savedInstanceState);
    }
}

可以看到这两个Fragment的代码基本上完全相同,都是重写了Fragment中相关的生命周期函数。

 

一、当没使用addToBackStack函数时。

1、使用replace()函数时:

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
 fragOne = new FragOne();
 fragmentTransaction.replace(R.id.frag_container, fragOne, fragNames[0]);
 fragmentTransaction.commit();

此时的生命周期和上述讲述的完全相同,即onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。

2、当我们使用replace()来替换一个已经存在的Fragment时(如腾讯QQ中当我们点击不同的底部按钮时会替换之前的Fragment),此时代码如下:

public void onClick(View v) {
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        switch (v.getId()) {
            case R.id.button1:
                if (fragOne == null) {
                    fragOne = new FragOne();
                    fragmentTransaction.replace(R.id.frag_container, fragOne, 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 (fragTwo == null) {
                    fragTwo = new FragTwo();
                    fragmentTransaction.replace(R.id.frag_container, fragTwo, fragNames[1]);
//                    fragmentTransaction.addToBackStack(fragNames[1]);
                } else {
                    Fragment fragment = fragmentManager.findFragmentByTag(fragNames[1]);
                    fragmentTransaction.replace(R.id.frag_container, fragment, fragNames[1]);
                }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();
    }

可以看到在上述代码中,我们将addToBackStack函数的调用注释起来,表示此时不适用该功能。此时的运行顺序为:

可以看到第一个Fragment的调用顺序为:onPause, onStop, onDestroyView, onDestroy, onDetach,这表明fragOne已经被FragmentManager销毁了,取而代之的是第二个Fragment,这也与replace()函数的名称和不适用addToBackStack相符合(即替换且不添加到Fragment返回栈中,既然是替换当然得去除前一个,添加第二个Fragment

这说明,在使用replace添加Fragment时如果没有调用addToBackStack方式的话,当FragmentManager替换Fragment时,是不保存Fragment的状态的,此时第二个Fragment将会直接替换前一个Fragment。

 

二、使用addToBackStack函数时。

(1)当我们使用replace函数且设置addToBackStack函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。即与不使用addToBackStack函数时的运行结果相同。

当我们使用replace函数且设置addToBackStack函数来替换之前显示的Fragmen't时运行结果为:

可以看到与之前的不使用addToBackStack相比,fragTwo的生命周期不受影响,而fragOne的生命周期和不使用addBackToStack函数相比,只存在三种状态的切换:onPauseonStop,onDestroyView。前者很好理解,因为addToBackStack函数顾名思义就是添加到回退栈中的意思,即当一个Fragment被另一个Fragment替换时会将之前的添加到回退栈中,因此也很好理解fragTwo的生命周期不受影响,因为是将被替换的添加到回退栈中,所以替换者不受影响。另外fragOne状态只到达onDestroyView,而无onDestroy,onDetach。这说明fragOne仅仅只是界面被销毁onDestroyView,而fragOne对象的实例依然被保存在FragmentManager中(因为无onDestroy,onDetach),它的部分状态依然被保存在FragmentManager中。我们可以来验证一下:

 

(2)我们点击按钮切换,让fragOne来替换当前显示的fragTwo,此时运行结果如下:

可以看到此时运行结果与fragTwo替换fragOne时fragOne的生命周期调用顺序非常相似,而且可以看到fragOne的生命周期是直接从onCreateView开始的,这也刚好对应上面的fragOne被fragTwo替换时生命周期到达onDestroyView,即之前的fragOne仅仅销毁了视图,而fragOne对象的实例依然被保存在FragmentManager中,所以此时只需要创建视图,即直接从onCreateView开始。

 

三、使用show()/hide()函数时:

首先要明白使用show()/hide()时一般是会使用addToBackStack,,因为要使用show()/hide()前提是该Fragment实例已经存在,只不过我们是否将其界面显示出来而已,因此我们需要使用addToBackStack函数将一个Fragment的实例对象保存在Fragment的回退栈中。此时代码如下:

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

当我们使用add()/show()函数初次显示一个Fragment运行结果为:onAttach, onCreate, onCreateView, onActivityCreated, onStart, onResume,Fragment处于运行状态。这个很好理解,不再赘述。

当我们点击按钮切换显示第二个Fragment时运行结果为:

可以看到此时fragOne无输出表示fragOne的生命周期不受影响,而fragTwo的输出结果与直接初次显示fragTwo时是一样的。其实这也很好理解因为在add()/show()/hide()顾名思义就是添加显示隐藏的意思,它都不会对另外的Fragment的生命周期起作用

Android 中的 Fragment 是一种模块化 UI 组件,可以嵌入到 Activity 中并拥有自己的生命周期Fragment生命周期与宿主 Activity 紧密相关,但又具备独立的生命周期流程。以下是 Fragment 生命周期的详细解析: ### Fragment 生命周期阶段 Fragment生命周期由多个回调方法组成,这些方法在特定的生命周期事件发生时被调用。 1. **onAttach()** 当 Fragment 被附加到宿主 Activity 时调用。此时 Fragment 与 Activity 建立了联系,可以获取到 Activity 的引用。这是 Fragment 生命周期的第一个回调方法[^5]。 2. **onCreate()** 在 Fragment 初始化时调用。通常用于执行一些非 UI 相关的初始化操作,例如恢复状态或创建 ViewModel 实例。这个阶段与 Activity 的 onCreate() 类似,但不涉及视图创建。 3. **onCreateView()** 用于创建 Fragment 的视图层次结构。在此方法中通常会通过 `LayoutInflater` 加载布局资源并返回根视图。如果不需要 UI,则可以返回 `null`。此阶段是 Fragment UI 初始化的核心部分。 4. **onViewCreated()** 在 onCreateView() 返回的视图创建完成后调用。适合进行视图的绑定和初始化操作,例如设置监听器或加载数据。 5. **onActivityCreated()** 表示宿主 Activity 已经完成其 onCreate() 方法。此时可以安全地访问 Activity 的 UI 元素和数据。此方法Fragment 与 Activity 完全绑定后调用[^5]。 6. **onStart()** Fragment 变得可见时调用。此时 Fragment 已经附加到窗口,并准备显示给用户。 7. **onResume()** Fragment 进入活跃状态,用户可以与之交互。此阶段是 Fragment 生命周期中最活跃的部分。 8. **onPause()** 当 Fragment 失去焦点但仍部分可见时调用。通常用于保存数据或释放资源。 9. **onStop()** 当 Fragment 完全不可见时调用。此时 Fragment 仍保留其状态和视图层次结构,但可能被系统回收以节省资源。 10. **onDestroyView()** 当 Fragment 的视图被销毁时调用。通常发生在 Fragment 被替换或移除时。此时可以释放与视图相关的资源。 11. **onDestroy()** Fragment 被销毁时调用。通常用于释放所有资源,例如取消异步任务或注销监听器。 12. **onDetach()** Fragment 与宿主 Activity 解除绑定时调用。这是 Fragment 生命周期的最后一个回调方法。 ### Fragment 与 Activity 生命周期的关系 Fragment生命周期与其宿主 Activity 紧密相关。当 Activity 的生命周期发生变化时,Fragment生命周期也会相应变化。例如: - 当 Activity 被创建时,Fragment 会依次执行 onAttach()、onCreate()、onCreateView() 和 onActivityCreated()。 - 当 Activity 被销毁时,Fragment 会依次执行 onDestroy() 和 onDetach()。 - 如果 Fragment 被隐藏或显示,可以通过 `onHiddenChanged(boolean hidden)` 方法进行处理[^2]。 ### Fragment 生命周期示例代码 以下是一个简单的 Fragment 示例,展示了如何实现部分生命周期方法: ```java public class ExampleFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); // Fragment 被附加到 Activity } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 初始化非 UI 相关的数据 } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // 创建 Fragment 的 UI return inflater.inflate(R.layout.fragment_example, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 初始化视图和数据 } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // 宿主 Activity 已经创建完成 } @Override public void onDestroyView() { super.onDestroyView(); // 释放与视图相关的资源 } @Override public void onDestroy() { super.onDestroy(); // 释放所有资源 } @Override public void onDetach() { super.onDetach(); // Fragment 与 Activity 解除绑定 } } ``` ### 生命周期图示 Fragment生命周期可以通过一张图来更直观地理解。生命周期图展示了 Fragment 从创建到销毁的整个过程,以及各个生命周期方法之间的关系。Fragment生命周期图可以在 [GitHub](https://github.com/xxv/android-lifecycle) 上找到[^2]。 ### 生命周期管理 在实际开发中,Fragment生命周期管理需要注意以下几点: - **避免内存泄漏**:在 Fragment 中持有 Activity 或 Context 的引用时,需要确保在生命周期结束时释放这些引用。 - **合理使用返回栈**:将 Fragment 添加到返回栈中可以实现用户点击返回键时回退到上一个 Fragment 的效果。未添加到返回栈的 Fragment 在替换时会被直接销毁。 - **动态管理 Fragment**:通过 `FragmentManager` 和 `FragmentTransaction` 可以动态地添加、替换或移除 Fragment。 ### 总结 Fragment生命周期是 Android 开发中的核心概念之一。通过理解 Fragment生命周期及其与 Activity 的关系,开发者可以更好地管理 UI 组件和资源,从而构建出更高效、更稳定的 Android 应用。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值