0
点赞
收藏
分享

微信扫一扫

Fragment add与replace的区别(1)(1),音视频开发需要哪些知识

眸晓 2022-01-31 阅读 101

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走生命周期创建流程。

第一点回答,描述完区别后;再来从源码角度描述replace本质是什么,replace本质就是将replace操作变为remove和add操作,旧的 Fragment走生命周期销毁流程,新传递的Fragment走生命周期创建流程。

举报

相关推荐

0 条评论