Fragment执行流程分析

fragment.mTag = tag;

}

if (containerViewId != 0) {

if (containerViewId == View.NO_ID) {

throw new IllegalArgumentException("Can’t add fragment "

  • fragment + " with tag " + tag + " to container view with no id");

}

if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {

throw new IllegalStateException("Can’t change container ID of fragment "

  • fragment + ": was " + fragment.mFragmentId

  • " now " + containerViewId);

}

fragment.mContainerId = fragment.mFragmentId = containerViewId;

}

addOp(new Op(opcmd, fragment));

}

add()方法实际上就是对设置进行封装,真正的添加是在commit()方法时执行

  • commit()提交流程

在这里插入图片描述

replace()方式添加Fragment


// 加载第一个Fragment V4包 兼容11以下的版本

FragmentManager fragmentManager = getSupportFragmentManager();

// 开启事物

FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

// 把第一个Fragment HomeFragment加载进来

mHomeFragment = new HomeFragment();

// 第一个参数是Fragment的容器id,需要添加的Fragment

fragmentTransaction.replace(R.id.main_tab_fl, mHomeFragment);

// 一定要commit

fragmentTransaction.commit();

replace()和add()同样调用的是doAddOp()方法,只是opcmd不一样

@Override

public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {

doAddOp(containerViewId, fragment, tag, OP_ADD);

return this;

}

@Override

public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {

if (containerViewId == 0) {

throw new IllegalArgumentException(“Must use non-zero containerViewId”);

}

doAddOp(containerViewId, fragment, tag, OP_REPLACE);

return this;

}

  • OP_ADD

switch (op.cmd) {

case OP_ADD:

case OP_ATTACH:

added.add(op.fragment);

break;

case OP_REMOVE:

case OP_DETACH: {

added.remove(op.fragment);

if (op.fragment == oldPrimaryNav) {

mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.fragment));

opNum++;

oldPrimaryNav = null;

}

}

可以看到OP_ADD直接执行的是added.add(op.fragment);添加操作

  • OP_REPLACE

case OP_REPLACE: {

final Fragment f = op.fragment;

final int containerId = f.mContainerId;

boolean alreadyAdded = false;

for (int i = added.size() - 1; i >= 0; i–) {

final Fragment old = added.get(i);

if (old.mContainerId == containerId) {

if (old == f) {

alreadyAdded = true;

} else {

// This is duplicated from above since we only make

// a single pass for expanding ops. Unset any outgoing primary nav.

if (old == oldPrimaryNav) {

mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));

opNum++;

oldPrimaryNav = null;

}

final Op removeOp = new Op(OP_REMOVE, old);

removeOp.enterAnim = op.enterAnim;

removeOp.popEnterAnim = op.popEnterAnim;

removeOp.exitAnim = op.exitAnim;

removeOp.popExitAnim = op.popExitAnim;

mOps.add(opNum, removeOp);

added.remove(old);

opNum++;

}

}

}

if (alreadyAdded) {

mOps.remove(opNum);

opNum–;

} else {

op.cmd = OP_ADD;

added.add(f);

}

OP_REPLACE首先吧cmd变成OP_REMOVE,然后执行的是added.remove(old);操作,然后执行 added.add(f);CMD变为OP_ADD

void executeOps() {

final int numOps = mOps.size();

for (int opNum = 0; opNum < numOps; opNum++) {

final Op op = mOps.get(opNum);

final Fragment f = op.fragment;

if (f != null) {

f.setNextTransition(mTransition, mTransitionStyle);

}

switch (op.cmd) {

case OP_ADD:

f.setNextAnim(op.enterAnim);

mManager.addFragment(f, false);

break;

case OP_REMOVE:

f.setNextAnim(op.exitAnim);

mManager.removeFragment(f);

break;

case OP_HIDE:

f.setNextAnim(op.exitAnim);

mManager.hideFragment(f);

break;

case OP_SHOW:

f.setNextAnim(op.enterAnim);

mManager.showFragment(f);

break;

case OP_DETACH:

f.setNextAnim(op.exitAnim);

mManager.detachFragment(f);

break;

case OP_ATTACH:

f.setNextAnim(op.enterAnim);

mManager.attachFragment(f);

break;

case OP_SET_PRIMARY_NAV:

mManager.setPrimaryNavigationFragment(f);

break;

case OP_UNSET_PRIMARY_NAV:

mManager.setPrimaryNavigationFragment(null);

break;

default:

throw new IllegalArgumentException("Unknown cmd: " + op.cmd);

}

if (!mReorderingAllowed && op.cmd != OP_ADD && f != null) {

mManager.moveFragmentToExpectedState(f);

}

}

if (!mReorderingAllowed) {

// Added fragments are added at the end to comply with prior behavior.

mManager.moveToState(mManager.mCurState, true);

}

}

执行的是 mManager.removeFragment(f);

removeFragment()会把上一个Fragment移除

mManager.addFragment(f, false);

addFragment() 会把新的Fragment添加到容器中

replace()的源码就是把之前的移除,会重新执行Fragment生命周期, 会重新绘制界面

封装工具类


package com.qufu.fragmentdemo.helper;

import android.support.annotation.IdRes;

import android.support.annotation.Nullable;

import android.support.v4.app.Fragment;

import android.support.v4.app.FragmentManager;

import android.support.v4.app.FragmentTransaction;

import java.util.List;

public class FragmentManagerHelper {

private FragmentManager mFragmentManager;

private int mContainerViewId;

/**

  • 构造函数

  • @param fragmentManager 管理类FragmentManager

  • @param containerViewId 容器布局id containerViewId

*/

public FragmentManagerHelper(@Nullable FragmentManager fragmentManager, @IdRes int containerViewId) {

this.mFragmentManager = fragmentManager;

this.mContainerViewId = containerViewId;

}

/**

  • 添加Fragment

*/

public void add(Fragment fragment) {

// 开启事物

FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

// 第一个参数是Fragment的容器id,需要添加的Fragment

fragmentTransaction.add(mContainerViewId, fragment);

// 一定要commit

fragmentTransaction.commit();

}

/**

  • 切换显示Fragment

*/

public void switchFragment(Fragment fragment) {

// 开启事物

FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();

// 1.先隐藏当前所有的Fragment

List childFragments = mFragmentManager.getFragments();

for (Fragment childFragment : childFragments) {

fragmentTransaction.hide(childFragment);

}

// 2.如果容器里面没有我们就添加,否则显示

if (!childFragments.contains(fragment)) {

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-LgaUrFC0-1715599642835)]

[外链图片转存中…(img-3oN8QYqw-1715599642836)]

[外链图片转存中…(img-rPBPVG02-1715599642836)]

[外链图片转存中…(img-UapndYmI-1715599642837)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值