当前位置: 首页 > news >正文

黑龙江城乡建设厅网站重庆网站建设 沛宣

黑龙江城乡建设厅网站,重庆网站建设 沛宣,微商城设计网站建设,做设计在哪个网站找图片关于作者#xff1a;CSDN内容合伙人、技术专家#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 #xff0c;擅长java后端、移动开发、商业变现、人工智能等#xff0c;希望大家多多支持。 目录 一、概览二、setContentView#xff08;#xff09;三… 关于作者CSDN内容合伙人、技术专家 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 擅长java后端、移动开发、商业变现、人工智能等希望大家多多支持。 目录 一、概览二、setContentView三、inflate四、view的绘制展示4.1 Activity.onResume4.2 WindowManager addView4.3 ViewRootImpl4.4 addWindow makeVisible 五、 推荐阅读 接 - 上 篇Activity创建后还只是调用了onCreate方法页面并没有展示出来还需要调用setContentView方法加载页面布局并进行渲染最后展示。 一、概览 本源码基于Android 12 看代码前我们先上一张ActivityWindow, DecorView三者之间的关系图 DecorView是整个ViewTree的最顶层View它是一个FrameLayout布局代表了整个应用的界面。 在该布局下面有标题view和内容view两个子元素。 Activity setContentView 核心就是PhoneWindow的setContentView方法其主要干了两件事 1.完成DecorView的创建与加载这个DecorView会在后面onresume后添加到window中 2.将MainActivity的布局加载到DecorView内的一个ViewGroup中 创建DecorView即installDecor方法其内部用到了两个核心的方法 1.generateDecor方法创建出DecorView对象 2.generateLayout方法完成这个DecorView对象的布局加载并完成了MainActivity的父容器的赋值即contentParent变量 先上一张流程图 二、setContentView 我们跟踪一下源码看看这个方法是怎么做的 public void setContentView(View view) {getWindow().setContentView(view);initWindowDecorActionBar();}这里window即为 PhoneWindow window的初始化是在 Acticity 创建的时候初始化 在Acticity对象创建后会调用attach方法 UnsupportedAppUsage(maxTargetSdk Build.VERSION_CODES.R, trackingBug 170729553)final void attach(Context context, ActivityThread aThread, ...) {attachBaseContext(context);mFragments.attachHost(null /*parent*/);mWindow new PhoneWindow(this, window, activityConfigCallback);mWindow.setWindowControllerCallback(mWindowControllerCallback);mWindow.setCallback(this);mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags ActivityInfo.FLAG_HARDWARE_ACCELERATED) ! 0);}PhoneWindow.java Overridepublic void setContentView(int layoutResID) {根view 为空则初始 mDecor viewif (mContentParent null) {installDecor();} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {mContentParent.removeAllViews();}if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {final Scene newScene Scene.getSceneForLayout(mContentParent, layoutResID,getContext());transitionTo(newScene);} else {// 将布局文件添加到 mContentParentmLayoutInflater.inflate(layoutResID, mContentParent);}mContentParent.requestApplyInsets();final Callback cb getCallback();if (cb ! null !isDestroyed()) {cb.onContentChanged();}mContentParentExplicitlySet true;}调用installDecor()进行DecorView的初始化private void installDecor() {mForceDecorInstall false;if (mDecor null) {// 创建出一个DecorView并返回mDecor generateDecor(-1);} else {mDecor.setWindow(this);}if (mContentParent null) {//对mContentParent进行赋值,作为Activity布局的父容器mContentParent generateLayout(mDecor);}}首先判断了mContentParent是否为null如果为空则执行installDecor方法同时初始化一个mContentParent这个就是Activity布局的父容器 三、inflate LayoutInflater.java public View inflate(LayoutRes int resource, Nullable ViewGroup root, boolean attachToRoot) {final Resources res getContext().getResources();View view tryInflatePrecompiled(resource, res, root, attachToRoot);if (view ! null) {return view;}XmlResourceParser parser res.getLayout(resource);try {return inflate(parser, root, attachToRoot);} finally {}}private NullableView tryInflatePrecompiled(LayoutRes int resource, Resources res, Nullable ViewGroup root, boolean attachToRoot) {try {Class clazz Class.forName( pkg .CompiledView, false, mPrecompiledClassLoader);Method inflater clazz.getMethod(layout, Context.class, int.class);View view (View) inflater.invoke(null, mContext, resource);if (view ! null root ! null) {XmlResourceParser parser res.getLayout(resource);try {AttributeSet attrs Xml.asAttributeSet(parser);advanceToRootNode(parser);ViewGroup.LayoutParams params root.generateLayoutParams(attrs);if (attachToRoot) {root.addView(view, params);} else {view.setLayoutParams(params);}} finally {parser.close();}}return view;} catch (Throwable e) {} finally {}return null;}布局就是这么添加进mContentParent中的。 但是view还是没有显示出来的此时代码所做的事情仅仅只是加载了布局并没有开始view的测量、布局、绘制工作。 对应方法是onMeasure, onLayout, onDraw这些操作在后面 四、view的绘制展示 每一个Activity组件都有一个关联的Window对象用来描述一个应用程序窗口。每一个应用程序窗口内部又包含一个View对象用来描述应用程序窗口的视图。 我们再看下图 Activity#onResume()之后才是布局由不可见变为可见的我们看源码 4.1 Activity.onResume ActivityThread.java 下面这个方法是在Activity onCreate创建后调用的handleResumeActivity不清楚的可以看前面app启动文章. Overridepublic void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {// 这个方法会调用 activity的 onResume 方法if (!performResumeActivity(r, finalStateRequest, reason)) {return;}final Activity a r.activity;// window 未被添加进 windowmanagerif (r.window null !a.mFinished willBeVisible) {// windowr.window r.activity.getWindow();// decorViewView decor r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm a.getWindowManager();WindowManager.LayoutParams l r.window.getAttributes();a.mDecor decor;} else if (!willBeVisible){}if (a.mVisibleFromClient) {if (!a.mWindowAdded) {// DecorView 添加到 windowwm.addView(decor, l);} else {a.onWindowAttributesChanged(l);}}if (!r.activity.mFinished willBeVisible r.activity.mDecor ! null !r.hideForNow) {使布局可见if (r.activity.mVisibleFromClient) {r.activity.makeVisible();}}r.nextIdle mNewActivities;} 在上面的代码中会先调用Activity的onResume 然后再是view的绘制最后将DecorView 设置 可见; 4.2 WindowManager addView WindowManagerImpl.java private final WindowManagerGlobal mGlobal WindowManagerGlobal.getInstance();...Overridepublic void addView(View view, ViewGroup.LayoutParams params) {mGlobal.addView(view, params, mDisplay, mParentWindow);}这里也是一个空壳代码调用WindowManagerGlobal WindowManagerGlobal.java public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {final WindowManager.LayoutParams wparams (WindowManager.LayoutParams) params;ViewRootImpl root;View panelParentView null;// 加锁synchronized (mLock) {//实例化ViewRootImpl类root new ViewRootImpl(view.getContext(), display);view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);mParams.add(wparams);// do this last because it fires off messages to start doing thingstry {// //调用ViewRootImpl.setView方法把DecorView作为参数传递进去root.setView(view, wparams, panelParentView, userId);} catch (RuntimeException e) {// BadTokenException or InvalidDisplayException, clean up.if (index 0) {removeViewLocked(index, true);}throw e;}}}在方法内部会通过跨进程方式向WMSWindowManagerService发起一个调用从而将DecorView最终加到Window上在这个过程中ViewRootImpl、DecorView和WMS会彼此关联。 最后WMS调用ViewRootImpl.performTraversals 方法开始View的测量、布局、绘制。 4.3 ViewRootImpl 一个 Window 对应着一个 ViewRootImpl 和 一个 VIew。这个 View 就是被 ViewRootImpl 操作的. 从上面代码我们可以看到ViewRootImpl的初始化是在WindowManagerGlobal的addView中 ViewRootImpl.java /*** We have one child*/public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {synchronized (this) {if (mView null) {mView view;mAdded true;int res; /* WindowManagerImpl.ADD_OKAY; */// 刷新布局的操作触发view的measure - layout - draw 操作requestLayout();try {//将 View 添加到 WMS 中res mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes, ...);} catch (RemoteException e) {} finally {}// Set up the input pipeline. 设置了一系列的输入通道CharSequence counterSuffix attrs.getTitle();mSyntheticInputStage new SyntheticInputStage();InputStage viewPostImeStage new ViewPostImeInputStage(mSyntheticInputStage);}}}首先会调用requestLayout方法来刷新布局然后将 View 添加到 WMS 中最后是view事件的处理 view事件的处理最后还是会回到了 PhoneWindow 中的 DecorView 来处理剩下的就是从 DecorView 开始将事件层层传递给内部的子 View 中了 这里就不展开 ViewGroup.javaOverridepublic boolean dispatchTouchEvent(MotionEvent ev) {}Overridepublic void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {checkThread();mLayoutRequested true;scheduleTraversals();}}final class TraversalRunnable implements Runnable {Overridepublic void run() {doTraversal();}}void doTraversal() {if (mTraversalScheduled) {performTraversals();}}requestLayout()最终会调用到performTraversals在这个方法中会调用 View 的 measure() layout() draw() 方法。 我们看下面源码 private void performTraversals() {final View host mView;if (mFirst || windowShouldResize || viewVisibilityChanged || params ! null|| mForceNextWindowRelayout) {try {if (!mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) {performConfigurationChange(new MergedConfiguration(mPendingMergedConfiguration),!mFirst, INVALID_DISPLAY /* same display */);}} catch (RemoteException e) {}if (!mStopped || wasReportNextDraw) {//View 的测量performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);if (measureAgain) {//View 的测量performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);}layoutRequested true;}}} else {}if (didLayout) {// View 的布局performLayout(lp, mWidth, mHeight);}if (!cancelDraw) {// View 的绘制performDraw();} else {}mIsInTraversal false; }4.4 addWindow makeVisible com.android.server.wm.Session.java Overridepublic int addToDisplay(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {return mService.addWindow(this, window, attrs, viewVisibility, displayId,UserHandle.getUserId(mUid), requestedVisibilities, outInputChannel, outInsetsState,outActiveControls);}Activity.java 把DecorView的状态设置为可见那么布局也就可见了void makeVisible() {if (!mWindowAdded) {ViewManager wm getWindowManager();wm.addView(mDecor, getWindow().getAttributes());mWindowAdded true;}mDecor.setVisibility(View.VISIBLE);}五、 推荐阅读 Java 专栏 SQL 专栏 数据结构与算法 Android学习专栏
http://www.huolong8.cn/news/106568/

相关文章:

  • 国内食品行业网站开发做图片网站 服务器
  • 深圳建设信息网站模版破解免费wordpress
  • 成都网站建设推怎么做贷款网站
  • 领航 网站设计文章修改网站
  • 网站建设知名网站开发流程文档
  • 烟台制作网站有哪些做网站付款会有凭证吗
  • 建设网站域名有了还要什么wordpress插件 评分
  • 网站建设方案模板高校中国空间站官网
  • 房产网站建设产品wordpress 两个主题
  • 浙江信息网查询系统网站如何做sem优化
  • 沂水网站开发天津做网站找谁
  • 网站建设公司电话网站的网页声明怎么做
  • 河北营销类网站设计苏州做网站优化公司哪家好
  • 网站的建设自己怎么建设一个网站
  • 巩义网站建设案例课堂高端网站建设高端网站建设专家
  • 优化过程中十大技巧关键词seo资源
  • 建设网站用户名是什么原因Wordpress 分表分库
  • 建立企业官方网站优秀网站建设报价
  • 高端+旅游+网站建设电脑上常用的办公软件
  • 上海做网站公wordpress admin ajax
  • asp.net做的网站要放到网上空间去_要放哪些文件上去苏州园区邮编
  • 厦门正规网站建设公司网站怎样快速排名
  • 网店推广网站天津网站建设培训班
  • 网站编辑制作黄山市建设工程造价管理站网站
  • 购物网站建设技术难点漂亮logo图片
  • 湖南长沙网站建番禺网站制作多少钱
  • 网站运营实训报告总结大学生创新项目申报书 做网站
  • 定制网站建设程序流程建筑网课推荐
  • 汉化主题做网站效果图wordpress建站流程
  • 成都网站编辑襄樊网站建设