深入理解WMS(四):从WMS的角度分析Activity之间的关系
system_server_AMS类图.png
Activity_Window_相关类图.png
system_server_AMS类图.png
总体类图.png
流程图.png
一、相关概念
1、ActivityThread:为应用程序的主线程类,所有的APK程序都有且仅有一个ActivityThread,程序的入口为该类static main()函数
Activity:Activity包含一个Window,该Window在Activity的attach方法中通过调用new PhoneWindow()创建一个window;
2、PhoneWindow:继承Window类,是把一个FrameLayout进行一定的包装,并提供了一组通用的窗口操作接口,内部包含一个DecorView
3、View:最基本的UI组件,表示屏幕上的一个矩形区域;
4、DecorView:该类是一个 FrameLayout 的子类,并且是 PhoneWindow 中的一个内部类。Decor的英文是 Decoration,即“修饰”的意思,DecorView 就是对普通的 FrameLayout 进行了一定的修饰,比如添加一个通用的 Title bar,并响应特定的按键消息等。;
5、Window:表示顶层窗口,管理界面的显示和事件的响应;每个Activity 均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口,该类提供了一组通用的窗口(Window)操作 API,这里的窗口仅仅是程序层面上的,WMS 所管理的窗口并不是 Window 类,而是一个 View 或者 ViewGroup 类,一般就是指DecorView 类,即一个 DecorView 就是 WmS 所管理的一个窗口。Window 是一个 abstract 类型。
6、WindowManager:一个interface,继承自ViewManager。所在应用进程的窗口管理器;有一个implementation WindowManagerImpl;
主要用来管理窗口的一些状态、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。
7、ViewRootImpl:通过IWindowSession接口与全局窗口管理器进行交互:界面控制和消息响应;WMS 管理客户端窗口时,需要通知客户端进行某种操作,这些都是通过异步消息完成的
二、步骤
Step1:
当启动Activity时,system_server进程通过AMS(ActivityManagerService)的远程代理ApplicationThreadProxy(即应用进程的Binder,IApplicationThread)的scheduleLaunchActivit(),标示SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION,底层binder驱动启动应用进程XXXActivity,到应用进程的ActivityThread的内部类ApplicationThread的父类ApplicationNative的onTransact,再到scheduleLaunchActivity().
Step2:
ApplicationThread的scheduleLaunchActivity:通过sendMessage(H.LAUNCH_ACTIVITY, r),发到UI线程的ActivityThread 的H处理即handleLaunchActivity:
ActivityThread.java
public final class ActivityThread {private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// Initialize before creating the activityWindowManagerGlobal.initialize();Activity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);...} }
}
其中WindowManagerGlobal.initialize;是先取到WMS(WindowManagerService)的远程代理IWindowManager
WindowManagerGlobal.java
public final class WindowManagerGlobal {public static void initialize() {getWindowManagerService();}public static IWindowManager getWindowManagerService() {synchronized (WindowManagerGlobal.class) {if (sWindowManagerService == null) {sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));try {sWindowManagerService = getWindowManagerService();ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowManagerService;}}
}
Activity a = performLaunchActivity(r, customIntent);使用ClassLoader加载XXXActivity,这其中会创建ContextImpl、如果Application还没启动过,会先把Applicaition创建并onCreate,然后调用XXXActivity的attach();
在attach中:会创建改activity的对应的window即PhoneWindow,以及phoneWindow和WindowManagerImpl关联:
Activity:
final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window) {attachBaseContext(context);mFragments.attachHost(null /*parent*/);mWindow = new PhoneWindow(this, window);mWindow.setWindowControllerCallback(this);mWindow.setCallback(this);mWindow.setOnWindowDismissedCallback(this);mWindow.getLayoutInflater().setPrivateFactory(this);mMainThread = aThread;mInstrumentation = instr;mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE),mToken, mComponent.flattenToString(),(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);if (mParent != null) {mWindow.setContainer(mParent.getWindow());}mWindowManager = mWindow.getWindowManager();mCurrentConfig = config;
}
其中:(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)获取到是WindowManagerImpl:
这边会走到ContextImpl.getSystemService:
class ContextImpl extends Context { @Overridepublic Object getSystemService(String name) {return SystemServiceRegistry.getSystemService(this, name);}
}
SystemServiceRegistry:
final class SystemServiceRegistry {public static Object getSystemService(ContextImpl ctx, String name) {ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);return fetcher != null ? fetcher.getService(ctx) : null;}private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =new HashMap<Class<?>, String>();private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =new HashMap<String, ServiceFetcher<?>>();private static int sServiceCacheSize;static {registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,new CachedServiceFetcher<AccessibilityManager>() {@Overridepublic AccessibilityManager createService(ContextImpl ctx) {return AccessibilityManager.getInstance(ctx);}});registerService(Context.WINDOW_SERVICE, WindowManager.class,new CachedServiceFetcher<WindowManager>() {@Overridepublic WindowManager createService(ContextImpl ctx) {return new WindowManagerImpl(ctx);}});
}
返回是new WindowManagerImpl(ctx);在performLaunchActivity函数中,走完attach后,继续调用mInstrumentation.callActivityOnCreate去实行XXXActivity的onCreate,这时候大家会写setContentView(R.layout.xxx)
Step3:
Activity.setContentView():
会调用getWindow().setContentView(layoutResID),即PhoneWindow类中的setContentView:主要是在PhoneWindow创建DecorView mDecor(This is the top-level view of the window, containing the window decor),然后从mDecor找出android.R.id.content: mContentParent(ViewGroup), 然后把activity设置的View添加到mContentParent.addView(view, params);
public void setContentView(@LayoutRes int layoutResID) {getWindow().setContentView(layoutResID);initWindowDecorActionBar();
}
PhoneWindow:
public class PhoneWindow extends Window implements MenuBuilder.Callback {public void setContentView(int layoutResID) {if (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 {mLayoutInflater.inflate(layoutResID, mContentParent);}mContentParent.requestApplyInsets();final Callback cb = getCallback();if (cb != null && !isDestroyed()) {cb.onContentChanged();}mContentParentExplicitlySet = true;}
}
Step4:
在ActivitThread.handleLaunchActivity函数走完performLaunchActivity后,接着走handleResumeActivity函数中,显示启动r = performResumeActivity(token, clearHide, reason);去走XXXActivity的onResume。
接着会对Activity的对应的window设置窗口类型:**l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION,**WMS是对窗口进行操作,每个activity对应一个窗口,Framework会定义好几种窗口类型,比如系统Window、应用程序window、子Window等。这边的type类型很重要,没有这个,window显示不出来的。
接着会调用到ViewManager wm = a.getWindowManager();wm.addView(decor, l);走到WindowManagerImpl.addView:
ActivityThread:
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {ActivityClientRecord r = mActivities.get(token);...r = performResumeActivity(token, clearHide, reason);...if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();WindowManager.LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}if (a.mVisibleFromClient && !a.mWindowAdded) {a.mWindowAdded = true;wm.addView(decor, l);}...}
Step5:
WindowManagerImpl的addView又调用到WindowManagerGlobal.getInstance()的addView:
这个函数会创建root = new ViewRootImpl(view.getContext(), display);然后保存到mRoots.add(root)
接着调用到 root.setView(view, wparams, panelParentView);
public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();@Overridepublic void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);}
}public final class WindowManagerGlobal {public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {...ViewRootImpl root;View panelParentView = null;synchronized (mLock) {...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 {root.setView(view, wparams, panelParentView);} catch (RuntimeException e) {}}
}
Step6:
ViewRootImpl.setView():
这个函数中,通过WindowManagerGloabl拿到IWindowSession mWindowSession及远程WMS的Seesion的对象,进行mWindowSession.addToDisplay,到system_server进程的Session中。
public final class ViewRootImpl implements ViewParent,View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {synchronized (this) {....try {res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mInputChannel);} }...}
}
这个mWindowSession是
public static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try {InputMethodManager imm = InputMethodManager.getInstance();IWindowManager windowManager = getWindowManagerService();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;}}
调用到WindowManagerService的openSession方法:
public class WindowManagerService extends IWindowManager.Stubimplements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {@Overridepublic IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,IInputContext inputContext) {if (client == null) throw new IllegalArgumentException("null client");if (inputContext == null) throw new IllegalArgumentException("null inputContext");Session session = new Session(this, callback, client, inputContext);return session;}
}
深入理解WMS(四):从WMS的角度分析Activity之间的关系相关推荐
- 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 机械爪角度与距离之间的关系
■ 背景 在博文舵机控制的机械爪 测试了舵机机械爪的运动.由于多级的角度与给定的指令之间存在着伺服(角度负反馈闭环)控制关系,因此可以近似为一个线性控制关系. 舵机的角度与两个机械爪之间的距离可以通过 ...
- DDD:四色原型、DDD、DCI之间的关系
PPT对应某个聚合. Des对应某个聚合或其它聚合内的实体或值对象. MI对应某个聚合. Role对应PPT(Data)在某个上下文(Context)执行某些交互(Interactive)的代理或装饰 ...
- 【Android 插件化】Hook 插件化框架 ( 从源码角度分析加载资源流程 | Hook 点选择 | 资源冲突解决方案 )
Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...
- 深入理解HashMap(三): 关键源码逐行分析之构造函数
前言 系列文章目录 上一篇我们说明了HashMap的hash算法, 说到HashMap在构造时会自动将table设为2的整数次幂. 本篇我们就来聊聊HashMap的构造函数. 本文的源码基于 jdk8 ...
- 信息系统项目管理师必背核心考点(四)UML类与类之间的关系
科科过<每天一小时 俩月拿证>为您带来软考信息系统项目管理师核心重点考点(四):UML类与类之间的关系,内含思维导图+真题.本资料由科科过整理. [信息系统项目管理师核心考点]UML类与类 ...
- 深入理解WMS(三):剖析Activity,View,Window之间的关系
这篇课程开头就说在"接触 Android 开发时,我始终认为它就是负责将 layout 布局中的控件渲染绘制出来的".的确,对于layout布局怎么跟Activity关联起来的,都 ...
- 浅谈WMS系统(SAP WMS系统及非SAP的WMS系统)
随着国内信息化.数字化的普及,WMS系统的实施越来越成为一个常规的操作.本文对此做简要的说明,具体包括如下内容 全球范围的WMS系统厂商 中国市场的WMS系统厂商 SAP提供的WMS 系统产品 SAP ...
最新文章
- OVS 端口抽象层次(四十)
- 深度学习框架TensorFlow(2.创建图,启动图)
- boost::math::barycentric_rational用法的测试程序
- 计算机原理课程设计陈宏,东北大学计算机组成基础原理课程教学设计.doc
- 一个类的两个接口有同名函数,JAVA如何调用
- linux udhcpc指令,linux下udhcpc的使用
- 计算机中丢失msvcr71.dll 问题解决
- java多态 -- 猫狗案列
- 支付宝支付对账单java_[Java]解析支付宝对账单csv
- Centos宝塔面板清理垃圾空间
- 时序分析 42 -- 时序数据转为空间数据 (一) 格拉姆角场
- 可以修饰的基团有:氨基类,NHBOC类,Fmoc类不等,DSPE-PEG7-Mal
- route和bridge是什么意思_请问ROUTE 和 BRIDGE 是怎么分别的!
- 离散数学复习:二元关系
- homebrew php 扩展,Mac homebrew-1.5以后安装php扩展的方法
- 安规电容(X电容,Y电容)的简单对比介绍
- 电脑开机遇到二维码怎么办?
- 从FASTA文件中批量提取指定序列【Python脚本】
- 据说vite还是有坑,不行,那就还用vue-cli吧,命令vue create gua12,记一下,可能过一个星期不看,又忘了
- 智慧社区解决方案的服务形式有哪些
热门文章
- linux脚本控制,linux控制脚本
- datagridview控件读写mysql数据库表格的方法_C#读写Access数据库、表格datagridview窗体显示代码实例...
- 泰尔指数r语言_还在用Excel算区位基尼系数?用geo.gini吧!
- ajax重复被调用,重复jQuery ajax调用
- dev 点击子控件触发panelcontrol事件_LINUX IIO子系统分析之二 IIO子系统数据结构分析...
- 中班机器人上课视频_中班机器人律动公开课
- sdio接口_多种接口的谷歌Coral模块,总有一款适合您~
- shell 脚本 变量 获取程序输出结果异常分析
- angular2-baidu-map网站中使用百度地图
- targetSdkVersion