Event事件

来源:互联网 发布:服装cad软件排名 编辑:程序博客网 时间:2024/04/28 08:58

上篇阐述了滑动,但是说到底就是对触摸事件的响应罢了,所以这里不得不说起Android的一套NB的事件处理体系。
我们先从Activity的创建来说起吧:
【1】ActivityManagerService创建Activity线程,激活一个activity
具体源代码解析:mSystemThread = ActivityThread.currentActivityThread();
String mTopAction = Intent.ACTION_MAIN;通过getHomeIntent()拿到Activity的info,调用堆栈管理员开启这个Activity,mStackSupervisor.startHomeActivity(intent, aInfo, reason);这个方法中调用了StackSupervisor类中的scheduleResumeTopActivities进行topActivity的恢复任务。
【2】系统调用startInstrumentation创建activity
【3】Activity创建后,使用setContentView设置用户UI,这些View被加进PhoneWindow的ContentParent中,并且由线程ActivityThread执行后续任务,线程拿到Window类的唯一实现类PhoneWindow,这个类中就可以看到基本onMeasure,setBackground,onLayout,onAttachToWindow等方法,这样Activity就attach到这个phonewindow中。并且通过final WindowManager wm = getWindowManager();获得了类Window中的WindowManager服务的实例。
【4】Activity线程继续执行,当执行到Activity.makeVisible是将DecoView加入到WindowManger中,WindowManger会为每个DecoView创建对应的ViewRoot
【5】每个ViewRoot拥有一个Surface,每个Surface将会调用底层库创建图形绘制的内存空间。这个底层库就是SurfaceFlinger。SurfaceFlinger同时也负责将个View绘制的图形合到一块(按照Z轴,即垂直于屏幕方向)显示到用户屏幕。
【7】平时我们绘制view都是在Canvas上绘制,它直接操作Surface。对于每个View的ui变更,Surface要通知到ViewRoot,然后 ViewRoot获取Canvas绘制,如果绘制完成,surfaceFlinger得到通知,合并Surface成一个Surface到设备屏幕。
从上面的输出过程分析,我们可以知道真正显示图形实际上跟Activity没有关系,完全由WindowManager来决定。 WindowManager是一个系统服务,因此可以直接调用这个服务来创建界面,并且更绝的是Dialog、Menu也是有WindowManager 来管理的,并且最底层都是Surface来,因此,常见开发游戏的人都推荐你使用SurfaceView来创建界面。
Android启动从ActivityThread类的main方法开始,定义了Android程序唯一一条线程,处理消息机制hander,线程控制Activity(通过setContentView将Ui设置到DecorView中)都attch到抽象类Window唯一一个实现类PhoneWindow,WindowManager为每个PhoneWindow内部类DecorView实例创建对应的ViewRoot,每个ViewRoot拥有一个Surface绘制。
这里写图片描述
这里写图片描述
当然还可以通过HierarchyViewer检测布局得到:
这里写图片描述
通过图中(这是用的toolBar视图)可以看出,ViewSub是之前FramLayout的位置,如今改为用到actionBar再进行加载,这也是5.0的不同的一点,可以看到导航栏、状态栏,toolBar等。
DecorView extends FrameLayout说明DecorView其实是一个扩展FramLayout。custom view的id为content,
Activity中findViewById其实就是调用getWindow().findViewById(),而Window中的findViewById其实调用的就是getDecorView().findViewById()。
@Nullable
public final View findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
return findViewTraversal(id);
}

到了findViewTraversal方法中没啥发现。

    @Override    protected View findViewTraversal(@IdRes int id) {        if (id == mID) {            return this;        }        final View[] where = mChildren;        final int len = mChildrenCount;        for (int i = 0; i < len; i++) {            View v = where[i];            if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {                v = v.findViewById(id);//回调,递归                if (v != null) {                    return v;                }            }        }        return null;    }

这个据说是ViewGroup中重写的View的方法,从这里可以看出,findViewById真正做的就是将id传进来,通过一个递归进行反复查找得到View,所以不如用注解+反射效率来的快些,所以啊,引用inject还不止让代码更加简洁,还更高效。

1 0