• 从源码方面来分析Fragment管理中 Add() 方法


    前言

    本篇我们就来讲讲Fragment管理中的 Add() 方法

    Add():

    在我们动态的添加、管理Fragment中,Add属于最基础的方法了; 用法也很简单,如下就是向Activity添加一个Fragment:
    getSupportFragmentManager().beginTransaction().add(R.id.fragmenta,new FragmentA()).commit();
    一般时候我们使用到Fragment的时候,都是不止一个,比如微信界面,底部导航有四个按钮,分别对应不同的四个Fragment,像这种的每点击一次底部按钮就切换一下界面的话,我们就可以使用Add()外加hide和show进行组合

    下面我们简单实现一下,这里我们就弄两个Fragment,
    这里我们的MainActivity的布局如下:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.shaoen.lenovo.myapplication.MainActivity">
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:id="@+id/fragmenta"/>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/fragmenta_button" 
                android:text="FragmentA"
                android:layout_width="0dp"
                android:layout_height="match_parent" 
                android:layout_weight="1"/>
            <Button
                android:id="@+id/fragmentb_button"
                android:text="FragmentB"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"/>
        </LinearLayout>
    </LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    下面看MainActivity的内容:

    package com.shaoen.lenovo.myapplication;
    
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentManager;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import com.shaoen.lenovo.myapplication.fragment.FragmentA;
    import com.shaoen.lenovo.myapplication.fragment.FragmentB;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private String  TAG=MainActivity.class.getSimpleName();
        private Button fragmentA_Button;
        private Button fragmentB_Button;
    private FragmentTransaction transaction;
        private FragmentManager fragmentManager;
        private Fragment fragment;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.i(TAG,"onCreate--执行了");
            setContentView(R.layout.activity_main);
            fragmentManager=getSupportFragmentManager();
            transaction=  fragmentManager.beginTransaction();
            fragment=new FragmentA();
            transaction.add(R.id.fragmenta,fragment,"FragmentA").commit();
    
            fragmentA_Button=(Button) findViewById(R.id.fragmenta_button);
            fragmentB_Button=(Button) findViewById(R.id.fragmentb_button);
            fragmentA_Button.setOnClickListener(this);
            fragmentB_Button.setOnClickListener(this);
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.i(TAG,"onStart--执行了");
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.i(TAG,"onResume--执行了");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.i(TAG,"onPause--执行了");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.i(TAG,"onStop--执行了");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.i(TAG,"onDestroy--执行了");
        }
    
        @Override
        public void onClick(View v) {
            transaction=  fragmentManager.beginTransaction();
            switch (v.getId()){
                case R.id.fragmenta_button:
                    if (fragment!=null)
                        transaction.hide(fragment);
                    fragment=  fragmentManager.findFragmentByTag("FragmentA");
                    if (fragment!=null){
                        transaction.show(fragment);
                    }
                    else {
                        fragment=new FragmentA();
                        transaction.add(R.id.fragmenta,fragment,"FragmentA").commit();
                    }
                    break;
               case R.id.fragmentb_button:
                    if (fragment!=null)
                        transaction.hide(fragment);
                fragment=  fragmentManager.findFragmentByTag("FragmentB");
                    if (fragment!=null){
                        transaction.show(fragment);
                    }
                    else {
                        fragment=new FragmentB();
                        transaction.add(R.id.fragmenta,fragment,"FragmentB").commit();
                    }
                    break;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    这里我们写的比较简单,主要是为了看一下他们的执行生命周期,在这里我把所以log都打印出来了

    刚开始运行时的log如下:

    I/MainActivity: onCreate--执行了
    I/FragmentA: onAttach--执行了
    I/FragmentA: onCreate--执行了
    I/FragmentA: onCreateView--执行了
    I/FragmentA: onActivityCreated--执行了
    I/FragmentA: onStart--执行了
    I/MainActivity: onStart--执行了
    I/MainActivity: onResume--执行了
    I/FragmentA: onResume--执行了
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    此时我们点击FragmentB按钮;

    I/FragmentB: onAttach--执行了
    I/FragmentB: onCreate--执行了
    I/FragmentB: onCreateView--执行了
    I/FragmentB: onActivityCreated--执行了
    I/FragmentB: onStart--执行了
    I/FragmentB: onResume--执行了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后我们在反复点击FragmentA和FragmentB按钮,发现没有任何log打印,此时证明FragmentA和FragmentB通过hide和show方法进行切换时,都只会初始化一次,

    下面我们看向replace这个方法

    replace:

    首先replace方法,其实是remove和add方法的组合; remove就是将一个Fragment从FragmentManager中删除,如果我们切换下一个Fragment时,上一个Fragment不需要了,可以直接使用replace,如果我们还需要的话,API中也提供了相应的方法,那就是加入回退栈addToBackStack()

    下面我们把MainActivity中的代码改一下:

      @Override
        public void onClick(View v) {
            transaction=  fragmentManager.beginTransaction();
            switch (v.getId()){
                case R.id.fragmenta_button:
                    if (fragment!=null)
                        transaction.hide(fragment);
                    fragment=  fragmentManager.findFragmentByTag("FragmentA");
                    if (fragment!=null){ Log.i(TAG,"fragment不为空");
    
                        transaction.show(fragment);
                    }
                    else {
                        Log.i(TAG,"fragment为空");
                        fragment=new FragmentA();
                        transaction.replace(R.id.fragmenta,fragment,"FragmentA").addToBackStack("FragmentA").commit();
                    }
                    break;
               case R.id.fragmentb_button:
                    if (fragment!=null)
                        transaction.hide(fragment);
                fragment=  fragmentManager.findFragmentByTag("FragmentB");
                    if (fragment!=null){
                        Log.i(TAG,"fragment不为空");
                        transaction.show(fragment);
                    }
                    else {
                        Log.i(TAG,"fragment为空");
                        fragment=new FragmentB();
                        transaction.replace(R.id.fragmenta,fragment,"FragmentB").addToBackStack("FragmentB").commit();
                    }
                    break;
            }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    这里我们就改了一下OnClick中的代码,这时我们再打印一下log看看:
    首先初始化时是一致的:

    这里写代码片

    此时我们点击FragmentB:

    12-18 21:48:14.227 21081-21081/com.shaoen.lenovo.myapplication I/MainActivity: fragment为空
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onPause--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStop--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onDestroyView--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onAttach--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreate--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreateView--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onActivityCreated--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStart--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onResume--执行了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    我们发现Fragment调用了destroy方法,此时我们再点击FragmentA:

    I/MainActivity: fragment不为空
    
    • 1

    此时发现FragmentA没有切换过来,这是因为,我们在FragmentManager中找到了FragmentA的实例,但是此时,FragmentA的界面已经被销毁了,所以我们看见的还是FragmentB,此时我们的OnClick改成如下:

       @Override
        public void onClick(View v) {
            transaction=  fragmentManager.beginTransaction();
            switch (v.getId()){
                case R.id.fragmenta_button:
                        fragment=new FragmentA();
                        transaction.replace(R.id.fragmenta,fragment,"FragmentA").addToBackStack("FragmentA").commit();
                    break;
               case R.id.fragmentb_button:
                        fragment=new FragmentB();
                        transaction.replace(R.id.fragmenta,fragment,"FragmentB").addToBackStack("FragmentB").commit();
                    break;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这时再打印一下log,

    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onPause--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStop--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onDestroyView--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onAttach--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreate--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreateView--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onActivityCreated--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStart--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onResume--执行了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onPause--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStop--执行了
    12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onDestroyView--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onAttach--执行了
    12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onCreate--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onCreateView--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onActivityCreated--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStart--执行了
    12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onResume--执行了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    此时发现每次切换时,都会调用Fragment都会重新调用onCreateView()到onDestroyView()的所有方法,其实就是Fragment的布局层整个销毁到重建的过程

    注: 当我们进行Fragment嵌套时,如果我们点击返回键,不想回到上一个Fragment,而想直接回到更往前一个,或者更往前的Fragment,我们可以使用FragmentManager.popBackStackImmediate (String tag, int flags)方法,弹出TAG为tag的Fragment,同时把此Fragment以上的Fragment全都弹出(弹出回退栈,即彻底销毁,detach)

    有需要文章中完整代码的同学 现在私信发送 “底层源码” 即可免费获取

    现在私信发送 “进阶” 还可以获取《更多 Android 源码解析+核心笔记+面试真题》

    最后我想说:

    对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

    技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

    Android 架构师之路还很漫长,与君共勉

  • 相关阅读:
    P1381 单词背诵【双指针】
    【CMN】Components组件汇总
    ValueError: invalid literal for int() with base 10: ‘‘
    面试:KOOM内存泄漏的监控
    实验五:Java多线程程序设计
    OpenAI开发者大会大模型圈开卷AI Agent? 实在智能布局前瞻已下“先手棋”
    探索 AI+开源的未来:Open Source Congress@日内瓦
    阿里,腾讯,百度等大厂都在采用的Git,据说都来脱形自这份文档
    【Android 屏幕适配】屏幕适配通用解决方案 ⑦ ( PercentRelativeLayout 百分比布局方案 | 该布局已废弃本方案仅做参考 )
    基于JavaWeb的校园故障报修系统(源码+数据脚本+论文+技术文档)
  • 原文地址:https://blog.csdn.net/m0_70748845/article/details/126246670