Fragment加载过程分析。

本文详细探讨了Android中Fragment的加载过程,从Activity的getFragmentManager()方法入手,揭示了FragmentManagerImpl在其中的作用,以及与FragmentManager和FragmentManagerState的关系。通过对抽象类FragmentManager的分析,加深对Fragment管理的理解。

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

Fragment加载到屏幕上的代码非常简单。getFragmentManager().beginTransaction().add(int addId,Fragment addFragment,String tag).commit();

首先看getFragmentMananger()方法:它定义在Activity中:

public FragmentManager getFragmentManager() {
        return mFragments;
    }

它只是直接返回了成员变量mFragments。这个变量的类型是FragmentManagerImpl.它是FragmentManager的子类。与FragmentManager和FragmentManagerState处于同一个文件中。而FragmentManager实际上是一个抽象类。

接着看第二个。beginTransaction():

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

它将此FragmentManager本身赋给了一个叫做BackStackRecord的类。并将此Manager的实例在内部用一个成员变量保存起来。用于做回退栈栈管理之类的操作。故名思义。这是用于做Fragment回退栈记录处理的类。接着往下看add方法。这个方法是定义在BackStackRecord类中。

public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
    doAddOp(containerViewId, fragment, tag, OP_ADD);
    return this;
}


这个方法里面直接将成员变量交给一个叫做doAddOp的方法进行处理。再多传了一个标志位。用于区分add、remove、replace等操作:

private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { 
        fragment.mFragmentManager = mManager; 
  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) { 
            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 op = new Op(); 
        op.cmd = opcmd; 
        op.fragment = fragment; 
        addOp(op); 
 }


这个方法中进行了一些保护性的判断。并将containerViewId和tag赋给要添加的fragment.并将此fragment放于一个Op的容器类中。类似我们常用的ViewHolder。它定义在BackStackRecord类中。而在add方法中传过来的参数OP_ADD。将它保存在了op类中的cmd变量中。

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


接着看addOp方法:

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


这个方法就是把封装了此fragment的op实例保存起来。并将设置的动画也加入其中。

到此add方法算是介绍完了。接下来是commit方法,它也是在BackStackRecord类中定义。

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


此处直接调用类中的commitInternal方法。传一个false进入。而我们知道fragment提交时还有一个叫做commitAllowingStateLoss的方法。这个方法内部也是直接调用commitInternal方法。但是传入一个true进入:

int commitInternal(boolean allowStateLoss) { 
        if (mCommitted) throw new IllegalStateException("commit already called"); 
        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this); 
        mCommitted = true; 
        if (mAddToBackStack) { 
            mIndex = mManager.allocBackStackIndex(this); 
        } else { 
            mIndex = -1; 
        } 
        mManager.enqueueAction(this, allowStateLoss); 
        return mIndex; 
 }


这个方法中将对此fragment进行入栈操作。使用FragmentManagerImpl对象的enqueueAction方法将将回退栈记录管理类传回去。
下面回到FragmentManagerImpl类中:

public void enqueueAction(Runnable action, boolean allowStateLoss) { 
        if (!allowStateLoss) { 
            checkStateLoss(); 
        } 
        synchronized (this) { 
            if (mActivity == null) { 
                throw new IllegalStateException("Activity has been destroyed"); 
            } 
            if (mPendingActions == null) { 
                mPendingActions = new ArrayList<Runnable>(); 
            } 
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值