最新Androidx Fragment的前世今生系列(二)之Fragment的生命周期

2,355 阅读3分钟

背景

Fragment依赖于Activity,它的生命周期也与Activity息息相关,下面这张来自官网的图,可以很好的说明这个问题,但是对于我们上一篇文章提到的两种添加Fragment的方式(静态添加和动态添加)而言,这其中Fragement与Activity生命周期的具体表现又略有不同,后面我们会结合具体的例子详细说明。

Fragment生命周期概述

函数描述
onAttach()将Fragment与宿主的Activity关联起来
onCreate()创建Fragment
onCreateView()创建Fragment视图
onActivityCreated()宿主Activity被创建
onStart()Fragment变得可见
onResume()Fragment可交互
onPause()Fragment可见但不可交互
onStop()Fragment不可见
onDestroyView()销毁Fragment视图
onDestroy()清除Fragment的状态
onDetach()解除Fragment与Activity绑定

实验一:以静态方式添加Fragment

MainActivity布局如下

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <fragment
           android:id="@+id/fragment_one"
           android:layout_width="match_parent"
           android:layout_weight="1"
           android:name="com.snow.fragmentdemo.FragmentOne"
           android:layout_height="match_parent">
       </fragment>
       <fragment
           android:id="@+id/fragment_two"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:layout_weight="1"
           android:name="com.snow.fragmentdemo.FragmentTwo">
       </fragment>
   </LinearLayout>
</FrameLayout>

效果如图 当我们打开app,生命周期函数执行顺序如图 从图中我们可以看到首先宿主Activity开始创建,但是在还未创建成功时就已经与FragmentOne绑定,然后FragmentOne开始创建,创建视图,然后Activity创建完成,然后调用onViewStateRestored(Bundle)方法存储FragmentOne的状态信息,然后FragmentOne可见,最后可交互。

当我们按回退建,回退出这个Activity,生命周期函数执行顺序入如图 从图中我们可以看出,当按下回退建,FragmentOne和Activity开始变得不可交互,不可见,然后FragmentOne销毁视图,清除状态,与Activity解除绑定,最后Activity销毁。

实验2:动态加入Fragment

关键代码如下

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private FragmentManager fm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("TEST","Activity creating");
        setContentView(R.layout.activity_main2);

        fm = getSupportFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        transaction.replace(R.id.content, new FragmentOne());
        //transaction.addToBackStack(null);
        transaction.commit();
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        FragmentManager fm = getSupportFragmentManager();
        switch (v.getId()) {
            case R.id.button1:
                FragmentTransaction transaction = fm.beginTransaction();
                transaction.replace(R.id.content, new FragmentOne());
                transaction.addToBackStack(null);
                transaction.commit();
                break;
            case R.id.button2:
                FragmentTransaction transaction2 = fm.beginTransaction();
                transaction2.replace(R.id.content, new FragmentTwo()).addToBackStack(null).commit();
                break;
        }
    }

效果如图 中间是一个FrameLayout,下面时两个按钮可以对Fragment进行切换,我将FragmentOne设置为了打开默认加载的Fragment,当我们打开app,生命周期函数执行顺序如下图 可以看到开始与静态加入是一样的,当我们点击two,跳转到FragmentTwo,结果如下 由于我们没有使用transaction.addToBackStack(null),所以FragmentOne直接被销毁了然后与Activity解除绑定。而且我们如果按下回退见,会直接退出Activity。当我们使用transaction.addToBackStack(null)时,前面的文章已经说过transaction.addToBackStack(null)让我们的操作入栈,可以回滚。点击跳转FragmentTwo结果如下 我们可以看到FragmentOne并没有被销毁,只是销毁了视图。因为视图销毁了,所以页面的内容也销毁了,那么如果我们使用add方法添加FragmentTwo,结果会是如何,如下图所示 我们可以看到,FragmentOne生命周期并未变化,视图也没被销毁。所以如果需要保留页面内容,可以选择add方法来替换Fragment,由于也调用了transaction.addToBackStack(null),当我们按下回退键就回到前一个Fragment,而且如果页面有editText,里面的内容不会消失。

最后

transaction.addToBackStack(null)是相对于add等操作而言的,如果进行一系列操作之后调用transaction.addToBackStack(null)然后提交,当你按下回退建,就相当于将那些操作取消,回到操作前的状态。

最新Androidx Fragment的前世今生系列(一)之Fragment的简单使用