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

新乡彩票网站建设项目外包和人力外包哪个好

新乡彩票网站建设,项目外包和人力外包哪个好,专门做电脑壁纸网站,wordpress 地图前言#xff1a; View绘制流程中#xff0c;主要流程是这样的#xff1a; 1.用户进入页面#xff0c;首先创建和绑定Window#xff1b; 2.首次创建以及后续vsync信号来临时#xff0c;会请求执行刷新流程#xff1b; 3.刷新流程完成后#xff0c;会通知SurfaceFlin…前言 View绘制流程中主要流程是这样的 1.用户进入页面首先创建和绑定Window 2.首次创建以及后续vsync信号来临时会请求执行刷新流程 3.刷新流程完成后会通知SurfaceFlinger读取数据以及刷新页面。 本篇就是大流程中的第一个环节重点讲解进入页面后Window是如何创建以及绑定到系统侧的。 本文的流程主要分为以下三大块 1.APP侧window和布局的创建流程 2.APP侧window是如何绑定ViewRootImpl以及注册到系统侧的 3.系统侧接收到window后是如何处理的。 一.APP侧Window和View创建 1.1 创建Window Activity启动时会经历performLaunchActivity和handleResumeActivity的流程而window的创建以及decorView的创建就是在launch的过程中。 我们首先看一下ActivityThread.performLaunchActivity中的代码 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {...//Activity的创建Activity activity null;activity mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//Activity的关联activity.attach();//执行Activity的onCreate流程mInstrumentation.callActivityOnCreate()... } 我们看一下activity.attach中实现的相关内容 //android.app.Activity final void attach(){//1mWindow new PhoneWindow();//3mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),...);mWindow.setColorMode(info.colorMode); }//com.android.internal.policy.PhoneWindow.java public PhoneWindow(UiContext Context context) {public PhoneWindow(UiContext Context context) {super(context);mLayoutInflater LayoutInflater.from(context);} }主要执行了以下的逻辑 1.创建了Activity所绑定的Window成员名为mWindow类型为PhoneWindow。 2.在PhoneWindow中mLayoutInflater赋值。我们的布局就是通过mLayoutInflater对象去解析的。 3.给Window对象绑定WindowManager这个WindowManager实际上是WindowManagerImpl。 所以此时Activity中的mWindow以及PhoneWindow中的mWindowManager和mLayoutInflater都已经有值了。 1.2 DecorView和ContentParent创建 接下来我们看下callActivityOnCreate的流程。Activity.onCreate流程没有什么有关window的逻辑但是一般我们都会在onCreate中调用setContentView这个方法中却大有玄机我们一起看一下 //android.app.Window.java public void setContentView(LayoutRes int layoutResID) {//1getWindow().setContentView(layoutResID); }//com.android.internal.policy.PhoneWindow public void setContentView(int layoutResID) {if (mContentParent null) {//2installDecor();}...//3mLayoutInflater.inflate(layoutResID, mContentParent); }private void installDecor() {if(mDecor null){mDecor generateDecor(-1);}if (mContentParent null) {mContentParent generateLayout(mDecor);} } 主要执行了以下的逻辑 1.调用Activity中所持有window去加载layout。 2.首次的时候通过installDecor方法去创建根布局DecorView以及容器布局mContentParent。mContentParent是Activity上所有的View的父容器。 3.通过mLayoutInflater对象去解析生成布局对象并且关联到mContentParent上。 具体的解析逻辑不是本文的核心这里就不去细讲了。 1.3 小结 至此Activity的创建和其onCreate的流程已经结束此时Activity中的成员变量mWindowManager和mWindow对象已经完成了赋值总结一下如下图所示 二.APP侧Window注册 2.1 Activity和ActivityClientRecord中成员变量赋值 在第一章中Activity所对应的window及其中的布局创建完成了所以下一步就是需要把这个window向系统做一个绑定这个流程主要是在Activity的onResume周期中执行的。 首先我们仍然看一下resume周期所对应的代码如下 //ActivityThread.java public void handleResumeActivity(ActivityClientRecord r, ...) {final Activity a r.activity;...if (r.window null !a.mFinished willBeVisible) {r.window r.activity.getWindow();...//1a.mDecor decor;//2l.type WindowManager.LayoutParams.TYPE_BASE_APPLICATION;//3wm.addView(decor, l);} }主要执行了以下的逻辑 1.把window中的decor赋值给Activity中的mDecor 2.设置Window.LayoutParams的type类型为WindowManager.LayoutParams.TYPE_BASE_APPLICATION;在安卓中type决定window图层优先级值越大优先级越高部分图层优先级如下 public static final int TYPE_BASE_APPLICATION 1;//默认Activity对应的图层 public static final int FIRST_SYSTEM_WINDOW 2000;//系统弹窗的图层 public static final int TYPE_TOAST FIRST_SYSTEM_WINDOW5;//Toast的图层 public static final int TYPE_SYSTEM_OVERLAY FIRST_SYSTEM_WINDOW6;//悬浮窗的图层等级 public static final int TYPE_APPLICATION_OVERLAY FIRST_SYSTEM_WINDOW 38;//同上用于替代上面那个 3.通过windowManager添加decor。这里wm的对象实际上是WindowManagerImpl而其中的addView方法中又交给了WindowManagerGlobal来处理相关代码如下 //WindowManagerImpl.java public void addView(NonNull View view, NonNull ViewGroup.LayoutParams params) {mGlobal.addView(view, params,...); } 2.2 WindowManagerGlobal装载Window 接下来我们看一下WindowManagerGlobal.addView()中的逻辑。 public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {ViewRootImpl root;View panelParentView null;...//1if (windowlessSession null) {root new ViewRootImpl(view.getContext(), display);} else {root new ViewRootImpl(view.getContext(), display, windowlessSession);}view.setLayoutParams(wparams);//2mViews.add(view);mRoots.add(root);mParams.add(wparams);//3root.setView(view, wparams, panelParentView, userId); } 主要执行了以下的逻辑 1.创建ViewRootImplViewRootImpl的角色是页面刷新显示流程的执行者。 2.WindowManagerGlobal的角色是维护客户端所有的页面的所以自然而然的其中就维护了很多集合。比如存储所有根布局的mView对象等等这里就是往集合中注册的。 UnsupportedAppUsage private final ArrayListView mViews new ArrayListView(); UnsupportedAppUsage private final ArrayListViewRootImpl mRoots new ArrayListViewRootImpl(); UnsupportedAppUsage private final ArrayListWindowManager.LayoutParams mParams new ArrayListWindowManager.LayoutParams(); 3.上面说到ViewRootImpl是流程的具体执行者那么window的绑定自然也是交给其来处理。所以这里通过ViewRootImpl.setView方法来负责。 2.3 ViewRootImpl负责视图的绑定 接下来我们就看下ViewRootImpl的setView()方法。 ViewRootImpl.java public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {...if (mView null) {mView view;...//1requestLayout();//2InputChannel inputChannel null;if ((mWindowAttributes.inputFeatures WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) 0) {inputChannel new InputChannel();}//3res mWindowSession.addToDisplayAsUser(...);}//mInputEventReceiver new WindowInputEventReceiver(inputChannel,Looper.myLooper()); }这一块的逻辑也是较为清晰的 首先通过requestLayout方法尝试进行首次View绘制的完整流程虽然这时window还没有绑定上但是并不影响View流程的开始毕竟View流程中只有最后的绘制流程才需要和SurfaceFlinger进行交互。 然后生成InputChannel对象这个对象类似于一个回调通过后面的binder接口传递给系统侧。后面window上的点击事件就会通过InputChannel回调通知到应用侧。后面把inputChannel绑定到WindowInputEventReceiver中所以APP侧点击事件的来源就是其中的onInputEvent方法。 最后把相关的对象传递给系统侧完成注册。传递的内容如下 int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs,in int viewVisibility, in int layerStackId, in int userId,in InsetsVisibilities requestedVisibilities, out InputChannel outInputChannel,out InsetsState insetsState, out InsetsSourceControl[] activeControls); int addToDisplayAsUser(IWindow window, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, in int userId, in InsetsVisibilities requestedVisibilities, out InputChannel outInputChannel, out InsetsState insetsState, out InsetsSourceControl[] activeControls); 整个流程如下图所示 给系统侧传递的数据列表如下 对象类型 成员变量名 解释 IWindow window 对应ViewRootImpl中的IWindow.Stub传递的一个binder对象 WindowManager.LayoutParams attrs window对应的layoutParams属性 int viewVisibility 根布局的显示状态 int layerStackId displayId显示区域的唯一ID int userId 应用的userId InsetsVisibilities requestedVisibilities InputChannel outInputChannel 事件分发流程中传递的通道 InsetsState insetsState InsetsSourceControl activeControls 三.系统侧Window绑定 介绍系统侧的流程前我们先对系统侧的几个核心类简单介绍下因为大多数的读者对于系统侧的了解较少。 3.1 核心类介绍 类名 功能介绍 com.android.server.wm.Session 一个session对应一个应用进程负责应用和系统之间的窗口注册/移除SurfaceSession注册等等。 SurfaceSession 这个类注册是native的实现。负责维护应用和surfaceFlinger之间的连接。所以APP刷新时是直接通知SF并不需要经过system_server。 WindowManagerService 顾名思义用于所有应用的窗口管理。这里只是维护窗口的关系并负责具体的渲染流程。 3.2 应用进程绑定唯一的IWindowSession 上一章有讲到一个应用会有一个维护所有的视图的容器WindowManagerGlobal那么它其中一定有一个负责和系统侧通信的对象这个对象就是IWindowSession。相关代码如下 //WindowManagerGlobal.java public static IWindowSession getWindowSession() {if (sWindowSession null) {IWindowManager windowManager getWindowManagerService();sWindowSession windowManager.openSession(...);} }//WindowManagerService.java Override public IWindowSession openSession(IWindowSessionCallback callback) {return new Session(this, callback); }也就是说WindowManagerGlobal中只会持有一个sWindowSession对象而WindowManagerGlobal对应一个应用的进程所以IWindowSession是绑定唯一一个应用进程的。IWindowSession是一个binder的引用其在系统侧的具体实现是Session。上面的addToDisplayAsUser方法就是通过IWindowSession中提供的binder方法。 3.3 把window注册到系统侧 接下来我们就看一下第二中讲到的addToDisplayAsUser()方法它负责把应用侧的Window向系统侧注册。我们看一下其在系统侧的实现 //Session.java class Session extends IWindowSession.Stub{public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities,InputChannel outInputChannel, InsetsState outInsetsState,InsetsSourceControl[] outActiveControls) {return mService.addWindow(this, ...);} } 逻辑很简单直接交给WindowServiceManger的addWindow方法去处理接下来我们就看下这个方法 //WindowManagerService.java public int addWindow(Session session, ...) {WindowState parentWindow null;...//1final DisplayContent displayContent getDisplayContentOrCreate(displayId, attrs.token);...//2WindowToken token displayContent.getWindowToken(hasParent ? parentWindow.mAttrs.token : attrs.token);...if (token null) {if( hasParent ){token parentWindow.mToken;} else if (){token new WindowToken.Builder(this, binder, type)} else {token new WindowToken.Builder(this, binder, type)}...}...//3final WindowState win new WindowState(this, session, );...if (openInputChannels) {win.openInputChannel(outInputChannel);}...//4win.openInputChannel(outInputChannel);...//5win.attach();win.initAppOpsState();...win.mToken.addWindow(win); } 首先根据displayId找到归属的DisplayContentDisplayContent的作用是用于跟踪一系列的WindowState 然后如果当前的window存在parent则去查询其parent的WindowToken。WindowToken顾名思义用于识别WindowState 接下来生成WindowState这里的WindowState和APP侧的Window是对应的WindowState就是在系统侧window的描述并负责和window进行通讯 然后绑定事件输入这里的outInputChannel就是APP侧传递过来的。 最后通过attch()方法完成绑定我们重点看一下这个方法 //WindowState.java void attach() {if (DEBUG) Slog.v(TAG, Attaching this token mToken);mSession.windowAddedLocked(); }//Session.java void windowAddedLocked() {if (mPackageName null) {mPackageName wpc.mInfo.packageName;}if (mSurfaceSession null) {mSurfaceSession new SurfaceSession();...mService.mSessions.add(this);}mNumWindow; } 简单来说一个应用首次完成window.attch()的时候初始化mPackageName和mSurfaceSession()。 而mSurfaceSession对应的就是显示在前台的区域它初始化后对应的就是native创建surface以及后续和surfaceFlinger交互的流程了这个我们后面的文章来讲解。 最后使用mNumWindow记录Window的数量。 3.4 小结 我们仍然做一个小的总结window注册在系统侧的实现。其实就是接受一个客户端传递过来的binder引用对象IWindow然后生成一个唯一的对应对象WindowState。并且在应用进程级别生成一个SurfaceSession去维护应用的ViewRootImpl和surfaceFlinger的关系。流程图如下 四.总结 最后我们做一下总结整个window的注册流程主要分为三块大块 1.create流程主要是各种对象的初始化。流程中完成客户端window的创建以及mDecormContentParent等相关成员变量的初始化 2.resume流程主要是window关系的维护。所以创建视图处理类ViewRootImpl并且使用其把window向系统侧申请绑定 3.系统收到后主要是生成window在系统侧的对象并记录。所以分别创建Window组的对象WindowToken和Window的系统侧对象WindowState并保存。 整体流程图如下 五.扩展性问题 1.如果onCreate中不调用setContentView那么会执行后面的流程吗 答会的即使不调用setContentView只是不会有ContentView但是DecorView仍然会创建和绑定的只不过这时候展示的会是黑屏。
http://www.tj-hxxt.cn/news/132437.html

相关文章:

  • 4444k面访问升最新网站网站开发安全管理
  • 广西住建局官方网站有人免费有片视频吗
  • 网站建设论文答辩WordPress接入广告
  • php网站开发用什么绍兴做网站哪家好
  • 深圳网站营销seo费用大淘客网站logo怎么做
  • 如何给一个网站做定时的更新南昌市科协网站
  • 门户网站建设服务收费工业设计 做自己的网站 知乎
  • 信息产业部icp备案中心网站新乡商城网站建设哪家好
  • 合肥的网站建设公司哪家好下述不属于网页制作工具
  • 仪器仪表网站制作徐州优化网站建设
  • 单页网站网址建筑必看六个网站
  • 霸州网站开发网站建设中英语如何说
  • 凯里网站建设哪家专业有个找人做任务赚返佣的网站
  • 设计素材网站哪个最好用wordpress后台二次开发
  • 设计得好的美食网站wordpress电影分享
  • jsp网站开发实例教程网络管理系统密码
  • 做那种事情的网站青岛科技网站建设
  • 学校网站建设成功织梦网站图片代码
  • 移动互联与网站开发编辑网站教程
  • 公章电子版在线制作网站四川建设工程信息网官网
  • 性价比最高网站建设电话正规的网站建设公
  • 网站 设计 工具网站建设中英版
  • 中恒建设职业技术培训学校网站网络营销首先要做什么
  • 学ui设计网站微转app是用网站做的吗
  • 大学生网站建设例题答案设计好的网站
  • 网站排名优化化快排优化广告设计有哪些
  • 数据库网站建设教程免费域名备案
  • 大型网站过程网站初期内容
  • 海南省建设网站首页网站流量的重要性
  • 做网站项目主要技术北京市网上服务平台登录