android窗体加载过程剖析之消息处理的注册机制
16lz
2021-01-26
这一篇是接着上一篇android窗体加载过程剖析之一Activity的初始化
的内容继续往下走。 在查阅了网上很多文章和源码之后,终于对android这一块的内容有了一定的了解。网上相似内容的文章似乎已经有蛮多篇了,不过我想在写文章的同时也可以进一步加深自己的理解,所以就再自行梳理了一遍这块内容。
由上一篇文章我们知道,Window类中存放的WindowManager实际上是一个WindowManagerImpl对象(LocalWindowManager相当于一个包装器):
源码路径:frameworks\base\core\java\android\view\Window.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/Window.java
源码路径:frameworks\base\core\java\android\view\WindowManagerImpl.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/WindowManagerImpl.java
int index = findViewLocked(view, false);
findViewLocked的内容:
源码路径:frameworks\base\core\java\android\view\ViewRootImpl.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/ViewRoot.java
这里将传入的窗体的根view存入了类变量mView中。并且在InputQueue中注册了消息接收通道以及接收消息并处理的对象。当有按键,滚动等事件发生时,就是通过这个渠道从底层通知到了Java层。
一个给应用提供了某种机制来接收输入事件的输入队列。这个类我只看了下,没有深究,里面有一些Native的函数,这个类相当于是一个桥梁供Java层调用Native层的方法。
的内容继续往下走。 在查阅了网上很多文章和源码之后,终于对android这一块的内容有了一定的了解。网上相似内容的文章似乎已经有蛮多篇了,不过我想在写文章的同时也可以进一步加深自己的理解,所以就再自行梳理了一遍这块内容。
由上一篇文章我们知道,Window类中存放的WindowManager实际上是一个WindowManagerImpl对象(LocalWindowManager相当于一个包装器):
源码路径:frameworks\base\core\java\android\view\Window.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/Window.java
public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { mAppToken = appToken; mAppName = appName; if (wm == null) { wm = WindowManagerImpl.getDefault(); } mWindowManager = new LocalWindowManager(wm, hardwareAccelerated); }那么接下来就看看WindowManagerImpl的代码:
源码路径:frameworks\base\core\java\android\view\WindowManagerImpl.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/WindowManagerImpl.java
private void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih, boolean nest) { if (false) Log.v("WindowManager", "addView view=" + view); if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException( "Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; ViewRootImpl root; View panelParentView = null; synchronized (this) { ... root = new ViewRootImpl(view.getContext()); root.mAddNesting = 1; if (cih == null) { root.mCompatibilityInfo = new CompatibilityInfoHolder(); } else { root.mCompatibilityInfo = cih; } view.setLayoutParams(wparams); if (mViews == null) { index = 1; mViews = new View[1]; mRoots = new ViewRootImpl[1]; mParams = new WindowManager.LayoutParams[1]; } else { index = mViews.length + 1; Object[] old = mViews; mViews = new View[index]; System.arraycopy(old, 0, mViews, 0, index-1); old = mRoots; mRoots = new ViewRootImpl[index]; System.arraycopy(old, 0, mRoots, 0, index-1); old = mParams; mParams = new WindowManager.LayoutParams[index]; System.arraycopy(old, 0, mParams, 0, index-1); } index--; mViews[index] = view; mRoots[index] = root; mParams[index] = wparams; } // do this last because it fires off messages to start doing things root.setView(view, wparams, panelParentView); }我们就从第一次启动Activity添加窗体的情况来说明,由于函数有点长,因此省略掉了这种情况下不会进入的代码。
int index = findViewLocked(view, false);
findViewLocked的内容:
private int findViewLocked(View view, boolean required) { synchronized (this) { final int count = mViews != null ? mViews.length : 0; for (int i=0; i<count; i++) { if (mViews[i] == view) { return i; } } if (required) { throw new IllegalArgumentException( "View not attached to window manager"); } return -1; } }是在当前的窗体栈中寻找指定的View,有的话就返回在数组中的索引。由于假定的是第一次加载,那么就是返回-1.
root = new ViewRootImpl(view.getContext()); root.mAddNesting = 1;接下来可以看到root被初始化,由于我的源码是4.0版本的,因此实例化的对象是ViewRootImpl,4,0以下是ViewRoot对象。等下再来分析下ViewRootImpl这个类,先继续往下走。
if (mViews == null) { index = 1; mViews = new View[1]; mRoots = new ViewRootImpl[1]; mParams = new WindowManager.LayoutParams[1]; }新启动的窗体的根View和ViewRootImpl都被添加到了类的成员变量中,WindowManagerImpl会负责维护这些窗体,并控制事件的分发。
root.setView(view, wparams, panelParentView);函数的最后,调用了ViewRootImpl.setView函数。
源码路径:frameworks\base\core\java\android\view\ViewRootImpl.java
源码中国链接:http://www.oschina.net/code/explore/android-2.2-froyo/android/view/ViewRoot.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView == null) { mView = view; mFallbackEventHandler.setView(view); mWindowAttributes.copyFrom(attrs); attrs = mWindowAttributes; ... if (mInputChannel != null) { if (mInputQueueCallback != null) { mInputQueue = new InputQueue(mInputChannel); mInputQueueCallback.onInputQueueCreated(mInputQueue); } else { InputQueue.registerInputChannel(mInputChannel, mInputHandler, Looper.myQueue()); } } ...}只贴我关心的而且又是看懂了的部分,嘿嘿。
这里将传入的窗体的根view存入了类变量mView中。并且在InputQueue中注册了消息接收通道以及接收消息并处理的对象。当有按键,滚动等事件发生时,就是通过这个渠道从底层通知到了Java层。
InputQueue
源码地址 http://www.oschina.net/code/explore/android-4.0.1/core/java/android/view/InputQueue.java
An input queue provides a mechanism for an application to receive incoming input events. Currently only usable from native code.一个给应用提供了某种机制来接收输入事件的输入队列。这个类我只看了下,没有深究,里面有一些Native的函数,这个类相当于是一个桥梁供Java层调用Native层的方法。
更多相关文章
- Android(安卓)网络框架之Retrofit2使用详解及从源码中解析原理
- Android(安卓)Mms专题之:Mms源码结构
- android棋牌游戏实例,提供源码。
- Android(安卓)抱歉,xxx已停止运行 源码分析
- Android开源中国客户端学习 截屏模块
- Android(安卓)OkHttp(一)源码出发探寻执行原理
- PackageInstaller 5.0源码分析静默安装与静默卸载
- launcher源码分析
- Android系统源码阅读(16):Android(安卓)应用线程的消息循环模型