**

Fragment的onCreateView创建的view是如果加入到Activity的过程分析

**
1.简单介绍一下fragment的使用
在activity的布局里添加一个ViewGroup并设置一个id,使用的时候通过这个id添加一个fragment。这个过程相信大家都非常的清楚所以很简单的说明一下。

2.开始正式说明这个添加过程
1,在FragmentActivity里有一个变量mFragments

 final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

这个mFragments 是用来管理控制fragment的,请看他的创建方法,new了一个HostCallbacks对象,这个对象是activity与fragmeController交互的回调

class HostCallbacks extends FragmentHostCallback<FragmentActivity> {public HostCallbacks() {super(FragmentActivity.this /*fragmentActivity*/);}@Overridepublic void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {FragmentActivity.this.dump(prefix, fd, writer, args);}@Overridepublic boolean onShouldSaveFragmentState(Fragment fragment) {return !isFinishing();}@Overridepublic LayoutInflater onGetLayoutInflater() {return FragmentActivity.this.getLayoutInflater().cloneInContext(FragmentActivity.this);}@Overridepublic FragmentActivity onGetHost() {return FragmentActivity.this;}@Overridepublic void onSupportInvalidateOptionsMenu() {FragmentActivity.this.supportInvalidateOptionsMenu();}@Overridepublic void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode);}@Overridepublic void onStartActivityFromFragment(Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) {FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode, options);}@Overridepublic void onStartIntentSenderFromFragment(Fragment fragment, IntentSender intent,int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,int extraFlags, Bundle options) throws IntentSender.SendIntentException {FragmentActivity.this.startIntentSenderFromFragment(fragment, intent, requestCode,fillInIntent, flagsMask, flagsValues, extraFlags, options);}@Overridepublic void onRequestPermissionsFromFragment(@NonNull Fragment fragment,@NonNull String[] permissions, int requestCode) {FragmentActivity.this.requestPermissionsFromFragment(fragment, permissions,requestCode);}@Overridepublic boolean onShouldShowRequestPermissionRationale(@NonNull String permission) {return ActivityCompat.shouldShowRequestPermissionRationale(FragmentActivity.this, permission);}@Overridepublic boolean onHasWindowAnimations() {return getWindow() != null;}@Overridepublic int onGetWindowAnimations() {final Window w = getWindow();return (w == null) ? 0 : w.getAttributes().windowAnimations;}@Overridepublic void onAttachFragment(Fragment fragment) {FragmentActivity.this.onAttachFragment(fragment);}@Nullable@Overridepublic View onFindViewById(int id) {return FragmentActivity.this.findViewById(id);}@Overridepublic boolean onHasView() {final Window w = getWindow();return (w != null && w.peekDecorView() != null);}}

在这个回调的方法都很重要,其中

         @Overridepublic FragmentActivity onGetHost() {return FragmentActivity.this;}@Nullable@Overridepublic View onFindViewById(int id) {return FragmentActivity.this.findViewById(id);}

这两个方法是把fragment的view添加到activity最重要的2个方法,onFindViewById(int id)的这个id 就是
我们activity布局时给fragment设置ViewGroup ID。
FragmentController 里的private final FragmentHostCallback<?> mHost;就是通过onGetHost方法赋值。

FragmentHostCallback里面的几个重要变量

 private final Activity mActivity;final Context mContext;private final Handler mHandler;final int mWindowAnimations;final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

这几个变量看名字也能猜出他们是干什么的,其中mFragmentManager 是主要负责管理fragment的各种操作,包括onCreateView这个方法

现在我们再看看FragmentManagerImpl这个类里的2个重要变量

 FragmentHostCallback mHost;FragmentContainer mContainer;

mHost就是HostCallbacks 的实例对象
mContainer看名字是一个Fragment的容器,他的代码如下:

public abstract class FragmentContainer {/*** Return the view with the given resource ID. May return {@code null} if the* view is not a child of this container.*/@Nullablepublic abstract View onFindViewById(@IdRes int id);/*** Return {@code true} if the container holds any view.*/public abstract boolean onHasView();/*** Creates an instance of the specified fragment, can be overridden to construct fragments* with dependencies, or change the fragment being constructed. By default just calls* {@link Fragment#instantiate(Context, String, Bundle)}.*/public Fragment instantiate(Context context, String className, Bundle arguments) {return Fragment.instantiate(context, className, arguments);}
}

instantiate用来创建fragment的实例,onFindViewById最后会通过

 @Nullable@Overridepublic View onFindViewById(int id) {return FragmentActivity.this.findViewById(id);}

这个方法来获取我们给fragment准备的ViewGroup并添加fragment onCreateView返回的view,这样fragment的view就添加到acti里了

那有人可能就要问了mContainer是在哪初始化的,在FragmentManagerImpl的如下方法里

public void attachController(FragmentHostCallback host,FragmentContainer container, Fragment parent) {if (mHost != null) throw new IllegalStateException("Already attached");mHost = host;mContainer = container;mParent = parent;}

再看看attachController是在哪调用的呢?这时又回到了FragmentController里

 public void attachHost(Fragment parent) {mHost.mFragmentManager.attachController(mHost, mHost /*container*/, parent);}

mHost 是不是很熟悉,前面介绍过了

3.最后看看mContainer是怎么添加view的

在FragmentManagerImpl的onCreateView方法里,方法比较长这里完整贴出方便看清楚过程
(说明一下这原码是在android.support.v4.app包下找的,不同版本内容可能略有不同)

@Overridepublic View onCreateView(View parent, String name, Context context, AttributeSet attrs) {if (!"fragment".equals(name)) {return null;}String fname = attrs.getAttributeValue(null, "class");TypedArray a =  context.obtainStyledAttributes(attrs, FragmentTag.Fragment);if (fname == null) {fname = a.getString(FragmentTag.Fragment_name);}int id = a.getResourceId(FragmentTag.Fragment_id, View.NO_ID);String tag = a.getString(FragmentTag.Fragment_tag);a.recycle();if (!Fragment.isSupportFragmentClass(mHost.getContext(), fname)) {// Invalid support lib fragment; let the device's framework handle it.// This will allow android.app.Fragments to do the right thing.return null;}int containerId = parent != null ? parent.getId() : 0;if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {throw new IllegalArgumentException(attrs.getPositionDescription()+ ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);}// If we restored from a previous state, we may already have// instantiated this fragment from the state and should use// that instance instead of making a new one.Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;if (fragment == null && tag != null) {fragment = findFragmentByTag(tag);}if (fragment == null && containerId != View.NO_ID) {fragment = findFragmentById(containerId);}if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"+ Integer.toHexString(id) + " fname=" + fname+ " existing=" + fragment);if (fragment == null) {fragment = mContainer.instantiate(context, fname, null);fragment.mFromLayout = true;fragment.mFragmentId = id != 0 ? id : containerId;fragment.mContainerId = containerId;fragment.mTag = tag;fragment.mInLayout = true;fragment.mFragmentManager = this;fragment.mHost = mHost;fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);addFragment(fragment, true);} else if (fragment.mInLayout) {// A fragment already exists and it is not one we restored from// previous state.throw new IllegalArgumentException(attrs.getPositionDescription()+ ": Duplicate id 0x" + Integer.toHexString(id)+ ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)+ " with another fragment for " + fname);} else {// This fragment was retained from a previous instance; get it// going now.fragment.mInLayout = true;fragment.mHost = mHost;// If this fragment is newly instantiated (either right now, or// from last saved state), then give it the attributes to// initialize itself.if (!fragment.mRetaining) {fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);}}// If we haven't finished entering the CREATED state ourselves yet,// push the inflated child fragment along. This will ensureInflatedFragmentView// at the right phase of the lifecycle so that we will have mView populated// for compliant fragments below.if (mCurState < Fragment.CREATED && fragment.mFromLayout) {moveToState(fragment, Fragment.CREATED, 0, 0, false);} else {moveToState(fragment);}if (fragment.mView == null) {throw new IllegalStateException("Fragment " + fname+ " did not create a view.");}if (id != 0) {fragment.mView.setId(id);}if (fragment.mView.getTag() == null) {fragment.mView.setTag(tag);}return fragment.mView;}

在这个很长的方法里通过fragment = mContainer.instantiate(context, fname, null);创建fragment,
通过 moveToState(fragment);来添加view。这个方法也很长里面通过不同状态进行不同的操作
这里只贴出create的部分

 case Fragment.CREATED:// This is outside the if statement below on purpose; we want this to run// even if we do a moveToState from CREATED => *, CREATED => CREATED, and// * => CREATED as part of the case fallthrough above.ensureInflatedFragmentView(f);if (newState > Fragment.CREATED) {if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);if (!f.mFromLayout) {ViewGroup container = null;if (f.mContainerId != 0) {if (f.mContainerId == View.NO_ID) {throwException(new IllegalArgumentException("Cannot create fragment "+ f+ " for a container view with no id"));}//通过id获取activity的ViewGroupcontainer = (ViewGroup) mContainer.onFindViewById(f.mContainerId);if (container == null && !f.mRestored) {String resName;try {resName = f.getResources().getResourceName(f.mContainerId);} catch (NotFoundException e) {resName = "unknown";}throwException(new IllegalArgumentException("No view found for id 0x"+ Integer.toHexString(f.mContainerId) + " ("+ resName+ ") for fragment " + f));}}f.mContainer = container;//调用fragment的onCreateView返回的view赋值f.mView = f.performCreateView(f.performGetLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);if (f.mView != null) {f.mInnerView = f.mView;f.mView.setSaveFromParentEnabled(false);if (container != null) {//把fragment创建的view添加到了activity的设置的ViewGroup里container.addView(f.mView);}if (f.mHidden) {f.mView.setVisibility(View.GONE);}f.onViewCreated(f.mView, f.mSavedFragmentState);dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,false);// Only animate the view if it is visible. This is done after// dispatchOnFragmentViewCreated in case visibility is changedf.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)&& f.mContainer != null;} else {f.mInnerView = null;}}f.performActivityCreated(f.mSavedFragmentState);dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);if (f.mView != null) {f.restoreViewState(f.mSavedFragmentState);}f.mSavedFragmentState = null;}

关键部分加入了注释,到这里整个过程就都说了,希望对大家有用,哪里时候的不对的请指出,谢谢

Fragment的onCreateView创建的view是如何加入到Activity的相关推荐

  1. FragmentTabHost切换Fragment时保存状态,避免切换Fragment走onCreateView和onDestroyView方法;...

    FragmentTabHost这个控件每次切换Fragment,都会走Fragment的onCreateView和onDestroyView方法,多以每次切换都会创建和销毁Fragment实例,先来看 ...

  2. android_基础_ViewPager中Fragment的重复创建、复用问题

    转载自:https://www.cnblogs.com/bimingcong/p/10276450.html ViewPager中Fragment的重复创建.复用问题 在ViewPager中的Frag ...

  3. LayoutInflater Factory创建自定义View

    文章目录 一.LayoutInflater类 LayoutInflater被用在哪里 1. LayoutInflater用于代码动态创建View 2. LayoutInflater用于Activity ...

  4. component是什么接口_【Android每日一题】从Activity创建到View呈现中间发生了什么?...

    前言 前段时间公司招人,作为面试官,我经常让面试者简述View的绘制流程.他们基本都能讲明白View的测量(measure).布局(layout).绘制(draw)等过程. 还有少数人会提到Decor ...

  5. UIBezierPath和CAShapeLayer创建不规则View(Swift 3.0)

    最近一个朋友在做图片处理的 App,想要实现类似 MOLDIV App 拼图的UI效果(如何创建不规则的 view),就问我有什么想法.我首先想到的就是 UIBezierPath+CAShapeLay ...

  6. Android官方开发文档Training系列课程中文版:创建自定义View之View的创建

    原文地址:http://android.xsoftlab.net/training/custom-views/index.html 引言 Android框架含有大量的View类,这些类用来显示各式各样 ...

  7. android 动态创建view,react-native动态创建Android View 无效果

    问题描述 react-native动态创建Android View 无效果,我想在react-native里面直接点击函数进行创建,也就是通过module中的方法创建View 问题出现的环境背景及自己 ...

  8. 创建指南针View的例子

    在接下来的例子里,你将通过扩展View类创建一个指南针View.它使用传统的指南针上升箭头来指示方向.当完成时,应该和图4-3看起来一样. 指南针是一个UI控件的例子,它需要完全不同的视觉显示,不同于 ...

  9. ViewPager中Fragment的重复创建、复用问题

    在ViewPager中的Fragment的生命周期  随着页面的切换 当前的展示页相邻的页面生命周期一直在变化 一开始 刚进入Activity时候,ViewPager默认初始化好前两个Fragment ...

最新文章

  1. 数据结构 线性存储 -- 栈 讲解
  2. 第11届 蓝桥杯-第1、2次模拟(软件类)真题-(2020年3月、4月)-官方讲解视频
  3. 一个老王开枪案例带你一步一步领略程序开发的魅力
  4. python代码_python爬虫19 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!
  5. python显示no matching distribution,Python使用pip安装No matching distribution found for PyYaml==5.3.1...
  6. “有人拿十几万很开心地走了” 滴滴裁员名额员工竟然抢破头 官方回应...
  7. C++/CLI思辨录之再谈继承
  8. NLP预训练家族 | Transformer-XL及其进化XLNet
  9. 20200708:动态规划复习day02
  10. python编写makefile_Python项目中的Makefiles
  11. 机器学习基础(四十五)—— 模拟退火(Simulated Annealing)
  12. dispatch_async 与 dispatch_get_global_queue 的使用方法
  13. 控制Dell PowerEdge R720的风扇转速 (利用IPMI)
  14. 《InfoGAN: Interpretable Representation Learning》翻译
  15. C/C++编程学习 - 第5周 ③ 圆锥体的体积
  16. 对 a = [lambda : x for x in range(3)] 的理解
  17. 调用函数Fact()来计算m!
  18. 飞机飞行轨迹可视化Tacview
  19. ubuntu各种实践笔记
  20. 线段树维护(最大区间和,最大子段和,最长连续上升子序列)

热门文章

  1. 关于CSMA/CA和CSMA/CD的区别
  2. RelativeLayout里各个控件的相对位置
  3. android relativelayout动态添加视图,android RelativeLayout 动态添加子View
  4. uni 加载图片时的空缺
  5. 上交所前总工程师白硕:Libra招招制敌,中国是全球唯一有能力的应对者(全文)...
  6. java常用的转义字符_java常用转义字符
  7. Gin+Gorm+sessions 搭建 golang web项目
  8. 网 络 工 程 师 之 独 孤 九 剑
  9. bbr29_单边加速利器TCP BBR 锐速最佳替代品 | 厘米天空
  10. 斯坦福大学计算机学什么,斯坦福大学计算机专业课程设置了哪些要学习?入学条件全面解析...