Fragment总结——源码个人分析

本文通过对Fragment源码的分析,探讨了ComponentCallbacks接口在Android四大组件中的应用,以及OnCreateContextMenuListener接口的作用。文章重点介绍了Fragment的LifecycleOwner和ViewModelStoreOwner特性,以及FragmentManagerImpl和BackStackRecord在管理Fragment中的关键角色。在Fragment内部,通过FragmentHostCallback获取Context,并通过FragmentManager和FragmentTransaction实现Fragment的添加、删除与管理。

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

上次说到了Fragment,还没有补源码解析,今天有空,在AS中写了一个Fragment,Ctrl点进去看看源码,总结总结。
这里我先从最初的Fragment开始看。
在这里插入图片描述
ComponentCallbacks是android.content.res.Configuration目录下的一个接口,里面定义了两个方法,Android四大组件都实现了这个接口.它有两个方法分别是用来实时更新设备资源配置的,另外一个是释放资源方便GC的。
OnCreateContextMenuListener接口是用来处理上下文菜单显示事件的监听接口。他只有一个方法,当某个View中显示上下文菜单时被调用,开发人员可以通过实现该方法来处理上下文菜单显示时的一些操作。
LifecycleOwner是Lifecycle 对象的持有者,它有一个方法就是获取Lifecycle对象。在Fragment中就是创建了一个LifecycleRegistry的对象,它是LifecycleRegistry的实现子类。
ViewModelStoreOwner是ViewModelStore对象的持有者,它有一个方法就是获取ViewModelStore对象。它的职责是在配置更改期间保留拥有的ViewModelStore。

    private static final SimpleArrayMap<String, Class<?>> sClassMap = new SimpleArrayMap();
    static final Object USE_DEFAULT_TRANSITION = new Object();
    static final int INITIALIZING = 0;
    static final int CREATED = 1;
    static final int ACTIVITY_CREATED = 2;
    static final int STARTED = 3;
    static final int RESUMED = 4;
    int mState = 0;
    Bundle mSavedFragmentState;
    SparseArray<Parcelable> mSavedViewState;
    @Nullable
    Boolean mSavedUserVisibleHint;
    int mIndex = -1;
    String mWho;
    Bundle mArguments;
    Fragment mTarget;
    int mTargetIndex = -1;
    int mTargetRequestCode;
    boolean mAdded;
    boolean mRemoving;
    boolean mFromLayout;
    boolean mInLayout;
    boolean mRestored;
    boolean mPerformedCreateView;
    int mBackStackNesting;
    FragmentManagerImpl mFragmentManager;
    FragmentHostCallback mHost;
    FragmentManagerImpl mChildFragmentManager;
    FragmentManagerNonConfig mChildNonConfig;
    ViewModelStore mViewModelStore;
    Fragment mParentFragment;
    int mFragmentId;
    int mContainerId;
    String mTag;
    boolean mHidden;
    boolean mDetached;
    boolean mRetainInstance;
    boolean mRetaining;
    boolean mHasMenu;
    boolean mMenuVisible = true;
    boolean mCalled;
    ViewGroup mContainer;
    View mView;
    View mInnerView;
    boolean mDeferStart;
    boolean mUserVisibleHint = true;
    Fragment.AnimationInfo mAnimationInfo;
    boolean mIsNewlyAdded;
    boolean mHiddenChanged;
    float mPostponedAlpha;
    LayoutInflater mLayoutInflater;
    boolean mIsCreated;
    LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    LifecycleRegistry mViewLifecycleRegistry;
    LifecycleOwner mViewLifecycleOwner;
    MutableLiveData<LifecycleOwner> mViewLifecycleOwnerLiveData = new MutableLiveData();

在Fragment里面创建了很多对象,有生命周期状态对象,ViewModleStore对象等等。接下来重点介绍一下下面几个类
从这儿就此开始介绍Fragment内部情况。
1.FragmentManagerImpl类
前者的mFragmentManager对象就是FragmentManagerImpl类型的。这个类是FragmentManager的子类。下面贴张图了解一下
在这里插入图片描述
这是他们之间的联系,其中最重要的联系红色字体标记的。
在FragmentHostCallback中有一个抽象方法onGetHost(),它在FragmentActivity(后面叫FMA)的内部类HostCallBacks中得到了实现,他的返回值是FMA本身,而FMA是继承于SupportActivity,SupportActivity又是继承Activity,所以追踪到底就有了Context上下文,那么如果说在Fragment中创建了FragmentHostCallback这个对象=,那么就意味着fragment获取了Context。对的,开发Fragment的人也想到了,所以他这么写的

public abstract class FragmentHostCallback<E> extends FragmentContainer{
	@Nullable
    private final Activity mActivity;
    @NonNull
    private final Context mContext;
    @NonNull
    private final Handler mHandler;
	...

 	@Nullable
    public abstract E onGetHost();

	...
	
    @Nullable
    public View onFindViewById(int id) {
        return null;
    }
    
    ...
 	
 	@Nullable
    Activity getActivity() {
        return this.mActivity;
    }

    @NonNull
    Context getContext() {
        return this.mContext;
    }

    @NonNull
    Handler getHandler() {
        return this.mHandler;
    }
}
public class FragmentActivity extends SupportActivity implements ViewModelStoreOwner, OnRequestPermissionsResultCallback, RequestPermissionsRequestCodeValidator {
		...
		class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
				...
				public FragmentActivity onGetHost() {
            		return FragmentActivity.this;
        		}
        		...
        		@Nullable
        		public View onFindViewById(int id) {
            		return FragmentActivity.this.findViewById(id);
        		}		
        		...
		}
...
}
public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner, ViewModelStoreOwner {
	...
	FragmentHostCallback mHost;
	..
	@Nullable
    public Context getContext() {
        return this.mHost == null ? null : this.mHost.getContext();
    }
    ...
    @Nullable
    public final FragmentActivity getActivity() {
        return this.mHost == null ? null : (FragmentActivity)this.mHost.getActivity();
    }
    ...
     @Nullable
    public final Object getHost() {
        return this.mHost == null ? null : this.mHost.onGetHost();
    }
    ...

}
 

在Activity中可以获取到FragmentManager对象了,因为FragmentActivity中又获取FragmentManager对象,而Activity又继承了FragmentActivity,所以大功告成。在FragmentManager中又一个获取了一个FragmentTransaction对象,这个对象就是实质上用来添加fragment和删除fragment的最终存储集合。但Fragmenttransaction是一个抽象类,最终实现是用BackStackRecord子类来完成的,所以稍微看一看以下的代码。

FragmentManagerImpl.class
public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }
public int allocBackStackIndex(BackStackRecord bse) {
        synchronized(this) {
            int index;
            if (this.mAvailBackStackIndices != null && this.mAvailBackStackIndices.size() > 0) {
                index = (Integer)this.mAvailBackStackIndices.remove(this.mAvailBackStackIndices.size() - 1);
                if (DEBUG) {
                    Log.v("FragmentManager", "Adding back stack index " + index + " with " + bse);
                }

                this.mBackStackIndices.set(index, bse);
                return index;
            } else {
                if (this.mBackStackIndices == null) {
                    this.mBackStackIndices = new ArrayList();
                }

                index = this.mBackStackIndices.size();
                if (DEBUG) {
                    Log.v("FragmentManager", "Setting back stack index " + index + " to " + bse);
                }

                this.mBackStackIndices.add(bse);
                return index;
            }
        }
    }
FragmentHostCallback.class
final FragmentManagerImpl mFragmentManager;
FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) {
        this.mFragmentManager = new FragmentManagerImpl();
        this.mActivity = activity;
        this.mContext = (Context)Preconditions.checkNotNull(context, "context == null");
        this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null");
        this.mWindowAnimations = windowAnimations;
    }
BackStackRecord.class
ArrayList<BackStackRecord.Op> mOps = new ArrayList();
public BackStackRecord(FragmentManagerImpl manager) {
        this.mManager = manager;
    }
public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
        this.doAddOp(0, fragment, tag, 1);
        return this;
    }

    public FragmentTransaction add(int containerViewId, Fragment fragment) {
        this.doAddOp(containerViewId, fragment, (String)null, 1);
        return this;
    }

    public FragmentTransaction add(int containerViewId, Fragment fragment, @Nullable String tag) {
        this.doAddOp(containerViewId, fragment, tag, 1);
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        Class fragmentClass = fragment.getClass();
        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.");
        } else {
            fragment.mFragmentManager = this.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 (containerViewId == -1) {
                    throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no 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;
            }

            this.addOp(new BackStackRecord.Op(opcmd, fragment));
        }
    }
    public int commit() {
        return this.commitInternal(false);
    }
    int commitInternal(boolean allowStateLoss) {
        if (this.mCommitted) {
            throw new IllegalStateException("commit already called");
        } else {
            if (FragmentManagerImpl.DEBUG) {
                Log.v("FragmentManager", "Commit: " + this);
                LogWriter logw = new LogWriter("FragmentManager");
                PrintWriter pw = new PrintWriter(logw);
                this.dump("  ", (FileDescriptor)null, pw, (String[])null);
                pw.close();
            }

            this.mCommitted = true;
            if (this.mAddToBackStack) {
                this.mIndex = this.mManager.allocBackStackIndex(this);
            } else {
                this.mIndex = -1;
            }

            this.mManager.enqueueAction(this, allowStateLoss);
            return this.mIndex;
        }
    }

总结一下,就是在Fragment中会创建很多关于生命周期,获取状态,存储数据的对象,以及他们的初始化,其中fragmentActivity是用来获取上下文以及拿到生命周期,以方便后续的方法调用和数据保存(他是通过FragmentHostCallback过渡进行数据绑定获取的)。BackStackRecord是进行动态添加删除提交Fragment的实现类,他也是需要FragmentManagerImpl来进行配合使用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值