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

浙江建设职业继续教育学院网站哪里做网络推广

浙江建设职业继续教育学院网站,哪里做网络推广,网站建设的认识,团队拓展活动游戏0. 相关分享 Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系 Android从屏幕刷新到View的绘制(二)之Choreographer、Vsync与屏幕刷新 1. 相关类 WindowManagerService&#xff0c…

0. 相关分享

Android从屏幕刷新到View的绘制(一)之 Window、WindowManager和WindowManagerService之间的关系
Android从屏幕刷新到View的绘制(二)之Choreographer、Vsync与屏幕刷新

1. 相关类

WindowManagerService,下文简称WMS

这是一个系统服务,由SystemServer启动,运行在一个Binder线程,管理着Android系统中所有的Window。

这有什么实际作用呢?除了刷新View,它还可以为其他服务提供Window管理的支持,例如当触摸屏幕时产生输入事件,InputManangerService可以通过WMS来拿到所有Window信息,找到合适的Window进行输入事件的派发,此后,Window就会把这个输入事件传递给顶级View,也就是DecorView,接着就进入到熟悉的事件分发机制了。

Window

表示一个窗口的抽象的概念,这是一个空实现的抽象类,在APP进程中,它有实现类PhoneWindow。

PhoneWindow

是Window的实现类,一个Activity对应着一个PhoneWindow,在PhoneWindow中有一个顶级View——DecorView

DecorView

Activity的根View,继承自FrameLayout

ViewRootImpl

负责DecorView下所有View的调度,例如invalidate()等,Activity下的所有View都会向上找到DecorView,最终找到ViewRootImpl来处理

WindowManagerImpl

它是WindowManager接口的实现类,WindowManager接口又继承自ViewManager,顾名思义它是管理View和Window关系的。ViewManager中规范了三个方法:addView(), updateViewLayout(), removeView()。这三个任务最后也交到了WindowManagerGlobal来处理

WindowManagerGlobal

它是一个单例设计,一个APP进程对应一个WindowManagerGlobal,持有WMS的binder引用,可以通过它来与WMS进行IPC(跨进程通信)交互。

它还拥有许多集合,例如mViews包含了进程下所有View,mRoots包含了进程下所有ViewRootImpl,mDyingViews包含了进程下所有要销毁的View。

2. 上述类间的关系图

Window是View的载体,我们想要对Window进行添加、删除、更新View,就要通过WindowManager,实际管理着是WindowManagerGlobal,它与WMS通过Session进行IPC通信,具体的实现交给了WMS处理。

VeznzR.png

WMS也会为每个WIndow创建一个WindowState来管理它们,具体的渲染工作交给了SurfaceFinger处理。本文只讨论View、Window、WindowManager与WMS的关系。

img

3. Window对View的管理

Window是抽象的概念,它的实现类为PhoneWindow,内部维护着一个DecorView,换句话说,WIndow是以View的形式呈现给用户的。Window对View的操作,实际是通过ViewRootImpl实现。使用过程中,我们不会接触并访问到Window,而是通过WindowMananger来进行操作。

接下来说的Window对View的管理其实具体来说是对DecorView的管理,一个Window对应一个DecorView。其中DecorView的创建、删除,就相当于Window的添加、删除,所以也有的地方说,这部分的讨论叫做window的创建、更新、删除。

3.1 Window对View的添加

WindowManager的实现类是WindowManagerImpl

//WindowManagerImpl
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.updateViewLayout(view, params);
}@Override
public void removeView(View view) {mGlobal.removeView(view, false);
}

WindowManagerImpl将对View的添加、删除、更新都交给了WIndowManagerGlobal,mGlobal是一个单例:

//WindowManagerGlobal
public static WindowManagerGlobal getInstance() {synchronized (WindowManagerGlobal.class) {if (sDefaultWindowManager == null) {sDefaultWindowManager = new WindowManagerGlobal();}return sDefaultWindowManager;}
}

首先我们看到WindowManagerGlobal的addView(),具体步骤大概如下:

  1. 各类数据检查
  2. 更新mViews、mRoots等集合
  3. 创建一个ViewRootImpl,将要添加的view交给它
public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {//1.数据检查//...ViewRootImpl root;View panelParentView = null;synchronized (mLock) {//2. 更新mViews/mRoots等集合root = new ViewRootImpl(view.getContext(), display);mViews.add(view);mRoots.add(root);mParams.add(wparams);//3.把要添加的view交给ViewRootImpltry {root.setView(view, wparams, panelParentView);} catch (RuntimeException e) {//...}}
}

ViewRootImpl添加到View之后,主要做了几件事:

  1. 调用requestLayout()异步刷新view
  2. 通过session与WMS通信,真正完成window的添加
//ViewRootImpl
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {synchronized (this) {//值维护一个view(DecorView)if (mView == null) {mView = view;int res;//1. 调用requestLayout绘制ViewrequestLayout();//...try {//通过session与WMS通信,完成window的添加res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mInputChannel);} catch (RemoteException e) {...}//...
}

首先,requestLayout()最后通过scheduleTraversals()来申请绘制,这部分我们在屏幕绘制的部分再详谈。只需要知道发起了重绘View的请求即可。

//ViewRootImpl
@Override
public void requestLayout() {if (!mHandlingLayoutInLayoutRequest) {//检查线程checkThread();//标志位mLayoutRequested = true;//请求绘制scheduleTraversals();}
}

当收到允许绘制的通知的时候,最终会进入到performTraversals(),从而对DecorView自顶向下地分发绘制流程,如measure/layout/draw。

requestLayout()之后,ViewRootImpl通过session通知WMS,去完成window的添加。IWindowSession是一个Binder引用,可以通过它来与WMS通信。WMS为每个应用创建一个单独的session,这个session可以通过WindowManagerGlobal获得。

public ViewRootImpl(Context context, Display display) {mContext = context;//实例化ViewRootImpl的时候,ViewRootImpl就从WIndowManagerGlobal中拿到了可用的sessionmWindowSession = WindowManagerGlobal.getWindowSession();...
}

看一下WindowManagerGlobal中如何提供session的:

public static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {//单例,如果已经有了,就不再创建了if (sWindowSession == null) {try {InputMethodManager imm = InputMethodManager.getInstance();//WMS的引用,这个是全局引用,和AMS一样,在ServiceManager中获取。IWindowManager windowManager = getWindowManagerService();//wms创建一个session交给当前客户端进程的WindowManagerGlobal。sWindowSession = windowManager.openSession(new IWindowSessionCallback.Stub() {@Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}},imm.getClient(), imm.getInputContext());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowSession;}
}

首先我们发现WindowManagerGlobal首先会拿到WMS的引用,然后才通过WMS创建一个session,用于后续的通信。我们知道,系统服务由ServiceMananger管理,可以全局获取到WMS的binder引用。但为了让WMS知道和它通信的到底是哪个window,这久需要单独创建一个session,客户端window通过session向WMS发起通信。

我们来看一下WMS是如何处理这个openSession()请求的:

//WindowManagerService
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,IInputContext inputContext) {//实例化了一个SessionSession session = new Session(this, callback, client, inputContext);return session;
}

Session是一个binder实体,它持有WMS的直接引用,客户端window可以通过session来间接地通知WMS做一些操作。

获取到session后,ViewRootImpl的setView()就进入到了最后一步:session.addToDisplay():

//Session
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,Rect outStableInsets, Rect outOutsets,DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {//mServices就是WMS,让WMS来addWindow()return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}

我们来到WMS的addWIndow()

//WindowManagerService
public int addWindow(Session session,IWindow client,...){//为session建立一个WindowState,可以通过这个WindowState来与客户端通信。final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid,session.mCanAddInternalSystemWindow);
}

至此,APP进程就成功将view注册到WMS中,同时,APP进程的WindowManagerGlobal可以通过session对WMS进行binder通信,WMS也可以通过WindowState来与WindowManagerGlobal进行binder通信。

3.2 Window对View的更新

我们再看到mGlobal.updateViewLayout(view,params);

//WindowManagerGlobal
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {//1. 参数检查if (view == null) {throw new IllegalArgumentException("view must not be null");}if (!(params instanceof WindowManager.LayoutParams)) {throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");}final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;//2.更新layoutParams以及mRoot中对应的ViewRootImplview.setLayoutParams(wparams);synchronized (mLock) {//找到这个view对应的ViewRootImpl是谁int index = findViewLocked(view, true);ViewRootImpl root = mRoots.get(index);mParams.remove(index);mParams.add(index, wparams);//更新ViewRootImpl,这里setLayoutParams()最后也会调用到scheduleTraversals()来请求重绘,细节不在这里讨论root.setLayoutParams(wparams, false);}
}

最后到了ViewRootImpl.setLayoutParams(),最后也会调用到scheduleTraversals()来请求重绘,View的绘制、刷新的细节不在本文中讨论。

3.3 WIndow对View的删除

对View的删除大概分为以下几步:

  1. 首先让ViewRootImpl用die来删除
  2. 然后将要删除的view记录到mGlobal的mDyingViews集合中。
  3. View可能立即删除 doDie(),也可能不是立即删,就放入队列
  4. 移除各种回调
  5. 最后通知WMS移除这个window

我们直接看到最后:

//ViewRootImpl
mWindowSession.remove(mWindow);

4. 都有哪些Window会进行这样的创建、更新、删除操作?

Activity、Dialog、Toast等都需要View,而View都需要依附于WIndow

先从简单的Dialog对Window的创建谈起,最后再长篇大论到Activity的Window的创建

4.1 Dialog 的window创建

Dialog的构造方法明显看打了PhoneWindow的实例化、WindowManager的引用(借以与WMS通信)

Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {//...//获取windowManagermWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//实例化PhoneWindowfinal Window w = new PhoneWindow(mContext);mWindow = w;//设置回调w.setCallback(this);w.setOnWindowDismissedCallback(this);w.setOnWindowSwipeDismissedCallback(() -> {if (mCancelable) {cancel();}});w.setWindowManager(mWindowManager, null, null);//...
}

接着来到setContentView,就是把视图布局交给DecorView,细节我们在Activity.ssetContent()中讨论,几乎一样的。我们再来看一下show()方法

public void show() {//...mDecor = mWindow.getDecorView();//...WindowManager.LayoutParams l = mWindow.getAttributes();boolean restoreSoftInputMode = false;if ((l.softInputMode& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {l.softInputMode |=WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;restoreSoftInputMode = true;}//使用WindowManager.addViewmWindowManager.addView(mDecor, l);//...
}

mWindowManager.addView()我们知道最后会通过session通知到WMS,需要创建一个window来展示这个dialog。

4.2 长篇大论 Activity 的 Window创建

大概步骤如下:

  1. APP进程启动时,会通知AMS,application启动好了,并把applicationThread这个binder实体引用交给AMS
  2. AMS再以此通知app进程的第一个activity启动
  3. Activity启动之前初始化WindowManagerGlobal
  4. 最后onResume()执行完毕后,将window的添加通知给WMS

我们直接切入重点,AMS -> ActivityStarter-> ActivityStackSupervisor->realStartActivity()->app进程->handleLaunchActivity(),在这个方法中主要调用了Activity几个回调:

  1. attach()
  2. onCreate()
  3. onStart()
  4. onResume()
//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// Initialize before creating the activityif (!ThreadedRenderer.sRendererDisabled) {GraphicsEnvironment.earlyInitEGL();}//创建单例,创建WMS引用 IWindowManagerWindowManagerGlobal.initialize();//启动activityperformLaunchActivity();//回调onResume()handleResumeActivity();
}

Activity.attach()主要做了几件事:

  1. 建立了一个与Activity一一对应的PhoneWindow实例mWindow
  2. 为mWindow设置一个WMS引用
  3. Activity的mWindowManager也持有WMS引用
public class Activity implements Window.Callback,Window.OnWindowDismissedCallback,WindowControllerCallback,...{private Window mWindow;//一个Activity有一个Window,实现类为PhoneWindowprivate WindowManager mWindowManager;//WMS的引用final void attach(...){//一个activity对应一个PhoneWindowmWindow = new PhoneWindow(Activit.this,window,...);//设置一些回调mWindow.setWindowControllerCallback(this);mWindow.setCallback(this);mWindow.setOnWindowDismissedCallback(this);//...//给Window设置一个WMS的引用mWindow.setWindowManager(//获取WMS的远程引用(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);//拿到WMS的引用mWindowManager = mWindow.getWindowManager();}
}

正常情况下,我们可能会在onCreate()中调用setContentView():

public void setContentView(int layoutResId){getWindow().setContentView(layoutResId);initWindowDecorActionBar();
}

getWindow()拿到的是mWindow,实现类是PhoneWindow,看到它的setContentView()

//PhoneWindow
private DecorView mDecor;
private ViewGroup mContentParent;public void setContentView(int layoutResId){if(mContentParent==null){installDecor();//创建decorView,如果没有的话}//...
}private void installDecor(){//1. mDecore初始化if(mDecor==null){mDecore = generateDecor(-1);//new DecoreView(phoneWindow.this)}//2. mContentParent初始化,mDecoreView下的第一个ViewGroupif (mContentParent == null) {mContentParent = generateLayout(mDecor);//根据xml属性配置Activity的默认版型样式}}protected ViewGroup generateLayout(DecorView decor){//...mDecor.startChanging();mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);//设置背景//...//设置title之类的mDecor.finishChanging();
}

Activity的DecorView是由PhoneWindow来管理的,包括mContentParent。最后来到handleResumeActivity(),需要注意的是:

  1. 首先回调onResume()
  2. 然后使用设置了的DecorView,或者给一个默认的DecorView,通知WMS要addView()

performResumeActivity()->Activity.performResume()->Activity.onResume()

//ActivityThread
final void handleResumeActivity(){//1.回调onResumer = performResumeActivity();//2.如果之前没有通过setContentView()设置mDecor,则给一个默认的Activity a = r.activity;//当前这个activityif(r.window==null){//如果activity在onResume之后还没有mDecor,则会在这里给一个View decor = r.window.getDecorView();//如果没有的话会PhoneWindow.installDecor()decor.setVisibility(View.INVISIBLE);//这个wm是一个WindowManager,它持有WMS的引用//WindowManager也是一个接口,实现类是WindowManagerImplViewManager wm = a.getWindowManager();a.mDecor = decor;if(a.mVisibleFromClient){if(!a.mWindowAdded){a.mWindowAdded= true;wm.addView(decor,l);//l:WM.LayoutParams}}   }
}

如果在onResume()结束之前,用户都没调用setContentView(),那么会在这里给到一个mDecor。

wm.addView(decor,l)-> WindowManagerGlobal.addView()

此后的工作我们之前就讨论过了,不过是创建一个ViewRootImpl来维护这个DecorView,请求绘制之后通过session让WMS来添加window。

Activity.onDestroy()时,进入到ActivityThread.handleDestroyActivity(),其中通知了WMS去removeView(),也就是移除这个Activity的Window。最后再通知AMS自己的销毁,ActivityManager.getService().activityDestroyed();

参考文献:

本文基于Android8.0源码分析。结合一些博客的思路进行编排。
https://juejin.cn/post/6863756420380196877
https://blog.csdn.net/hfy8971613/article/details/103241153


文章转载自:
http://erinaceous.c7629.cn
http://fordize.c7629.cn
http://ergastulum.c7629.cn
http://vaulted.c7629.cn
http://manufacturer.c7629.cn
http://klooch.c7629.cn
http://overbrilliant.c7629.cn
http://krumhorn.c7629.cn
http://condescend.c7629.cn
http://flipper.c7629.cn
http://abirritant.c7629.cn
http://archimedes.c7629.cn
http://wolfer.c7629.cn
http://railophone.c7629.cn
http://ineducability.c7629.cn
http://unconditional.c7629.cn
http://nudnik.c7629.cn
http://untruss.c7629.cn
http://noctule.c7629.cn
http://thionic.c7629.cn
http://hornworm.c7629.cn
http://adurol.c7629.cn
http://chantage.c7629.cn
http://aerostat.c7629.cn
http://englisher.c7629.cn
http://amour.c7629.cn
http://hyfil.c7629.cn
http://glacieret.c7629.cn
http://climatotherapy.c7629.cn
http://occupationist.c7629.cn
http://malaceous.c7629.cn
http://ne.c7629.cn
http://parakeet.c7629.cn
http://galloon.c7629.cn
http://radicalism.c7629.cn
http://vicuna.c7629.cn
http://leucopenia.c7629.cn
http://newfoundlander.c7629.cn
http://forager.c7629.cn
http://zanily.c7629.cn
http://coxsackie.c7629.cn
http://expect.c7629.cn
http://clintonia.c7629.cn
http://depolarize.c7629.cn
http://marriageability.c7629.cn
http://synonymic.c7629.cn
http://gusset.c7629.cn
http://blockette.c7629.cn
http://alienative.c7629.cn
http://backcloth.c7629.cn
http://hypochondria.c7629.cn
http://famished.c7629.cn
http://zoochory.c7629.cn
http://nobbily.c7629.cn
http://consecration.c7629.cn
http://norland.c7629.cn
http://crania.c7629.cn
http://telefilm.c7629.cn
http://appropriative.c7629.cn
http://coercionist.c7629.cn
http://noho.c7629.cn
http://configurate.c7629.cn
http://naupathia.c7629.cn
http://sherwani.c7629.cn
http://nonage.c7629.cn
http://geologician.c7629.cn
http://drugola.c7629.cn
http://satisfiable.c7629.cn
http://gleamingly.c7629.cn
http://kiva.c7629.cn
http://declassee.c7629.cn
http://parcener.c7629.cn
http://hellenic.c7629.cn
http://coy.c7629.cn
http://underlead.c7629.cn
http://achromobacter.c7629.cn
http://leash.c7629.cn
http://quale.c7629.cn
http://breadless.c7629.cn
http://dilatorily.c7629.cn
http://antipodes.c7629.cn
http://cachinnation.c7629.cn
http://omen.c7629.cn
http://misaligned.c7629.cn
http://ovolo.c7629.cn
http://jurant.c7629.cn
http://odovacar.c7629.cn
http://ngf.c7629.cn
http://testify.c7629.cn
http://fatalize.c7629.cn
http://gavelock.c7629.cn
http://rumormonger.c7629.cn
http://magnetomotive.c7629.cn
http://cicatrise.c7629.cn
http://virginia.c7629.cn
http://sequin.c7629.cn
http://derive.c7629.cn
http://effluvium.c7629.cn
http://hagride.c7629.cn
http://unquenchable.c7629.cn
http://www.zhongyajixie.com/news/89017.html

相关文章:

  • php网站模块百度客服怎么转人工电话
  • 定制网站开发多少钱温州网站快速排名
  • 网站型销售怎么做网店代运营哪个好
  • metro 导航网站企业seo顾问
  • 智能网站搭建平台郑州专业seo推荐
  • 网站中怎么做搜索框湖南seo公司
  • 建设网站怎么备案济南做seo排名
  • 湛江模板建站服务商建立网站怎么搞
  • 母版页和窗体做网站例子广告联盟接单平台
  • 网站制作的困难与解决方案推广代理
  • 做谷歌网站口碑营销ppt
  • 做的网站没流量吗武汉网络推广平台
  • 无锡企业网站制作公司沧州网站建设推广
  • 黑龙江住房和城乡建设网seo翻译
  • 班级网站设计毕业论文seo用什么论坛引流
  • wordpress 隐藏日期重庆可靠的关键词优化研发
  • 网站的推广代码是什么资源搜索
  • 易语言做网站外挂2023国内外重大新闻事件10条
  • 中文一级a做爰片免费网站最佳磁力搜索天堂
  • 网站做游戏活动网络市场调研的方法
  • 恩施做网站seo综合查询平台官网
  • 佛山定制网站建设推广是做什么工作的
  • 网站如何在百度如何做网站的教程
  • c 网站开发日期控件100个电商平台
  • 四川省人民政府2022年森林防火命令seo搜外
  • 佛山做网站哪家公司好郑州seo哪家专业
  • 惠州专业网站建设公司哪里有郑州网站
  • 手机网站开发人员选项营销型网站建设流程
  • 那个网站做外贸好seo简单速排名软件
  • 衢州建筑裂缝加固工程厦门seo蜘蛛屯