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)) {

建议

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

Android高级技术大纲

面试资料整理

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

[外链图片转存中…(img-UVBAF9GH-1715048250210)]

[外链图片转存中…(img-QYbgvaLw-1715048250211)]

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 30
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值