Fragment add与replace的区别(1)(1)

case OP_REMOVE:
case OP_DETACH: {
added.remove(op.fragment);
}
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–) {
//如果当前已有Fragment添加到Activity中,取出已添加的Fragment
final Fragment old = added.get(i);
if (old.mContainerId == containerId) {
if (old == f) {
//如果replace的是同一个Fragment
alreadyAdded = true;
} else {
//不是同一Fragment,删除旧的Fragment
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 {
//当前Activity中同一个id没有添加Fragment或者同一个id存在Fragment,但replace传递fragment和已有的不是同一个实例,将操作类型replace修改为add
op.cmd = OP_ADD;
added.add(f);
}
}
break;
}
}
return oldPrimaryNav;
}

由上面代码分析可知

  1. 如果当前Activity同一个id还没有添加Fragment,replace操作和add操作一样。

即执行两者操作生命周期变化:onAttach->onCreate->onCreateView->onActivityCreated->onStart-onResume,

Fragment所依附的Activity销毁时,执行onPause->onStop->onDestoryView->onDestory->onDetach

  1. 如果当前Activity同一个id存在Fragment,replace传递的Fragment实例和已存在的Fragment实例一样,replace无效果,这点从上面源码中可以看出

  2. 如果当前Activity同一个id存在Fragment,replace传递的Fragment实例和已存在的Fragment实例不一样,replace操作会转换为 remove和add操作,即删除旧的Fragment,添加新的Fragment,这点从上面代码中也可以看出来。

旧的Fragment执行 onPause->onStop->onDestoryView->onDestory->onDetach

新的Fragment执行 onAttach->onCreate->onCreateView->onActivityCreated->onStart-onResume

总的来说BackStackRecord#expandOps就是修正replace的操作,将replace 变为 remove和add操作。

无论是remove,add 我们发现操作的都是mOps集合。mOps中存放的是事务操作的序列。根据流程图在接下来第11步骤也就是BackStackRecord#executeOps会执行mOps存放的事务操作。

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;
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);
}

}
//执行Fragment生命周期
mManager.moveToState(mManager.mCurState, true);
}

  1. 最后简单总计下:

面试官在问add和replace区别,我们可以从实际使用中真实感受出发 即第一点回答,描述完区别后;再来从源码角度描述replace本质是什么,replace本质就是将replace操作变为remove和add操作,旧的 Fragment走生命周期销毁流程,新传递的Fragment走生命周期创建流程。

如果要从源码角度回答细致一点,那么可以回答:

  1. 如果当前Activity同一个id还没有添加Fragment,replace操作和add操作一样。

即执行两者操作生命周期变化:onAttach->onCreate->onCreateView->onActivityCreated->onStart-onResume,

Fragment所依附的Activity销毁时,执行onPause->onStop->onDestoryView->onDestory->onDetach

  1. 如果当前Activity同一个id存在Fragment,replace传递的Fragment实例和已存在的Fragment实例一样,replace无效果。

  2. 如果当前Activity同一个id存在Fragment,replace传递的Fragment实例和已存在的Fragment实例不一样,replace操作会转换为 remove和add操作,即删除旧的Fragment,添加新的Fragment。

旧的Fragment执行 onPause->onStop->onDestoryView->onDestory->onDetach

新的Fragment执行 onAttach->onCreate->onCreateView->onActivityCreated->onStart-onResume

现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套【Android进阶学习视频】、【全套Android面试秘籍】、【Android知识点PDF】。如有需要获取资料文档的朋友,可以点击我的GitHub免费获取!

最后

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

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

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

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

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

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值