Fragment在生命周期中是如何走到onCreateView的(一)

本文深入探讨Fragment在Android中的生命周期,从一个简单的调用开始,分析beginTransaction、replace操作,再到commitAllowingStateLoss,详细解析FragmentManager、BackStackRecord和生命周期状态的转换过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近遇到了一个Crash,于是想探究一下Fragment在onCreateView之前都干了什么?生命周期是如何跟Activity同步的?Fragment的视图又是如何添加到布局中的?
一步一步来探究。

以API 24为例

从一个简单的调用开始:

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = QrGenerateFragment.newInstance("a", "b");
fragmentManager.beginTransaction()
        .replace(R.id.container, fragment)
        .commitAllowingStateLoss();

这里涉及到了几个类:FragmentManagerFragmentManagerImplFragmentTransactionBackStackRecord

先看beginTransaction

FragmentManager.java

@Override
public FragmentTransaction beginTransaction() {
    return new BackStackRecord(this);
}

其实是创建了一个BackStackRecord。从字面意思理解,就是回退栈的记录。
同时将FragmentManager的实例传给BackStackRecord

public BackStackRecord(FragmentManagerImpl manager) {
    mManager = manager;
}

然后是replace(R.id.container, fragment)

FragmentTransaction.java

@Override
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
    return replace(containerViewId, fragment, null);
}

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

传入一个ViewGroup的id,fragment实例,之后,tag设置为null

这里OP_REPLACE是代表什么操作:

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;

这里传的是OP_REPLACE,
如果是add的方式,就是OP_ADD

然后来看一下doAddOp

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
    final Class fragmentClass = fragment.getClass();
    final int modifiers = fragmentClass.getModifiers();

     // 一开始是进行一些状态的判断
    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.");
    }

     // 然后给fragment的manager赋值
    fragment.mFragmentManager = mManager;

     // 判断的tag的一致性,如果tag不一致,就报错
    if (tag != null) {
        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;
    }

    if (containerViewId != 0) {
          // View.NO_ID是-1
        if (containerViewId == View.NO_ID) {
            throw new IllegalArgumentException("Can't add fragment "
                    + fragment + " with tag " + tag + " to container view with no id");
        }
          // fragmentId跟containerViewId不一致也报错,应该是之前有在其他的container里用过。
        if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
            throw new IllegalStateException("Can't change container ID of fragment "
                    + fragment + ": was " + fragment.mFragmentId
                    + " now " + containerViewId);
        }
          // 这里可以看出,会把containerViewId赋值给fragmentId
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    }

    Op op = new Op();
    op.cmd = opcmd;
    op.fragment = fragment;
    addOp(op);
}

Op是一个回退栈存储内容

static final class Op {
    Op next;
    Op prev;
    int cmd;
    Fragment fragment;
    int enterAnim;
    int exitAnim;
    int popEnterAnim;
    int popExitAnim;
    ArrayList<Fragment> removed;
}

用于双向链表结构,Op包括上一个,下一个,还有动画参数等

void addOp(Op op) {
    if (mHead == null) {
        mHead = mTail = op;
    } else {
        op.prev = mTail;
        mTail.next = op;
        mTail = op;
    }
    op.enterAnim = mEnterAnim;
    op.exitAnim = mExitAnim;
    op.popEnterAnim = mPopEnterAnim;
    op.popExitAnim = mPopExitAnim;
    mNumOp++;
}

然后把新的Op加到链表中

这里replace就看完了.

下面是commitAllowingStateLoss

在BackStackRecord中

/**
* Entry of an operation on the fragment back stack.
*/
final class BackStackRecord extends FragmentTransaction implements
  FragmentManager.BackStackEntry, Runnable {

BackStackRecord是继承自FragmentTransaction的,并且实现了Runnable接口

@Override
public int commit() {
    return commitInternal(false);
}

@Override
public int commitAllowingStateLoss() {
    return commitInternal(true);
}

int commitInternal(boolean allowStateLoss) {
    if (mCommitted) throw new IllegalStateException("commit already called");
    if (FragmentManagerImpl.DEBUG) {
        Log.v(TAG, "Commit: " + this);
        LogWriter logw = new LogWriter(TAG);
        PrintWriter pw = new PrintWriter(logw);
        dump("  ", null, pw, null);
    }
    mCommitted = true;
    if (mAddToBackStack) {
          // 如果之前添加到回退栈里,会分配一个id,这里暂时不深究
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }

     // 把BackStackRecoed实例传入
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

FragmentManager

/**
* Adds an action to the queue of pending actions.
*
* @param action the action to add
* @param allowState
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值