这一篇是接着上一篇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
    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层的方法。

更多相关文章

  1. Android(安卓)网络框架之Retrofit2使用详解及从源码中解析原理
  2. Android(安卓)Mms专题之:Mms源码结构
  3. android棋牌游戏实例,提供源码。
  4. Android(安卓)抱歉,xxx已停止运行 源码分析
  5. Android开源中国客户端学习 截屏模块
  6. Android(安卓)OkHttp(一)源码出发探寻执行原理
  7. PackageInstaller 5.0源码分析静默安装与静默卸载
  8. launcher源码分析
  9. Android系统源码阅读(16):Android(安卓)应用线程的消息循环模型

随机推荐

  1. Android野史系列:1.安卓操作系统架构与应
  2. Android多媒体开发 Pro Android(安卓)Med
  3. Android(安卓)学习笔记 一、目录结构
  4. 性能优化系列-Android(安卓)内存泄漏例子
  5. Android(安卓)Window类解析
  6. Android平板低迷,与iPAD差在哪里?
  7. 初涉Android
  8. AllJoyn+Android开发案例-android跨设备
  9. android默认开启adb调试方法分析
  10. Android(安卓)计时器Timer用法