上一篇Android:FragmentTransaction我们大概介绍了FragmentManager的大致工作流程,知道了每个动作都会添加到Op队列里,并由FragmentTransaction进行管理,那么我们就来看看FragmentTransaction的具体内容。
首先FragmentTransaction中定义了每个动作的常量值。
static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;
static final int OP_SET_PRIMARY_NAV = 8;
static final int OP_UNSET_PRIMARY_NAV = 9;
static final int OP_SET_MAX_LIFECYCLE = 10;
在这些值里面,我们看到了非常熟悉的一些操作,比如add,hide,replace等,每个动作都对应一个值。
static final class Op {
//每个动作对应的命令数值
int mCmd;
//要操作的那个fragment
Fragment mFragment;
//进入动画
int mEnterAnim;
//退出时动画
int mExitAnim;
int mPopEnterAnim;
int mPopExitAnim;
//声明周期状态
Lifecycle.State mOldMaxState;
Lifecycle.State mCurrentMaxState;
}
那每个动作是如何添加到事务的呢?当我们调用事务的add,hide,show等操作时,从前面文章知道:
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
这个transaction其实是BackStackRecord对象,所以会调用BackStackRecord中对应的方法,比如hide操作。
//BackStackRecord.java
public FragmentTransaction hide(@NonNull Fragment fragment) {
......
//调用父类
return super.hide(fragment);
}
//父类:FragmentTransaction.java
public FragmentTransaction hide(@NonNull Fragment fragment) {
addOp(new Op(OP_HIDE, fragment));
return this;
}
最终调用父类的addOp方法,创建了一个Op对象,并传入OP_HIDE值和要操作的Fragment对象,然后将其添加到mOps列表中。
ArrayList<Op> mOps = new ArrayList<>();
void addOp(Op op) {
mOps.add(op);
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
我们在添加fragment到事务时,add方法有两个重载方法。
transaction.add(f1,"f1");
transaction.add(R.id.layout_f,f1,"f1");
一个是不传容器id,一个需要传,第一个方法,其实就是调用第二个方法,然后id传0。
public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
对于第二个方法,我们来看看。
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
//反射
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
//检查fragment是否是匿名类,是不是public的,是不是静态类,是不是嵌套类等
if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
|| (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
+ " must be a public static class to be properly recreated from"
+ " instance state.");
}
//如果有标签tag
if (tag != null) {
//检查tag,不允许修改已经存在的tag
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
+ fragment + ": was " + fragment.mTag
+ " now " + tag);
}
fragment.mTag = tag;
}
//如果设置里容器Id
if (containerViewId != 0) {
//如果没有为容器设置ID
if (containerViewId == View.NO_ID) {
throw new IllegalArgumentException("Can't add fragment "
+ fragment + " with tag " + tag + " to container view with no id");
}
//如果fragment已经有容器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;
}
//添加Op到队列
addOp(new FragmentTransaction.Op(opcmd, fragment));
}
再来看attach和detach方法,detach会将fragment从UI界面移除,即使调用show也无法再次显示出来。调用attach后,fragment会重新显示在界面上。
findViewById(R.id.tv_1).setOnClickListener((v -> {
FragmentTransaction t = fragmentManager.beginTransaction();
t.detach(f1);
t.commitNow();
}));
findViewById(R.id.tv_2).setOnClickListener((v -> {
FragmentTransaction t = fragmentManager.beginTransaction();
t.attach(f1);
t.commitNow();
}));
原文地址:https://blog.csdn.net/bdmh/article/details/134669296
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_5059.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!