概述
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
本文主要学习一下与View相关的一些原理与实践,如常用的 View.post 和 ViewTreeObserver 的原理,以及老生常谈的 View 事件分发机制的源码解读,自定义 View 及其滑动冲突的解决方式等。有关Android绘制相关的看Android-View绘制原理。
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
本文主要学习一下与View相关的一些原理与实践,如常用的 View.post 和 ViewTreeObserver 的原理,以及老生常谈的 View 事件分发机制的源码解读,自定义 View 及其滑动冲突的解决方式等。有关Android绘制相关的看Android-View绘制原理。
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
从 Android-Window机制原理 和 Android-Choreographer原理 中了解到,无论是通过 WindowManager.addView 方法添加View,还是调用 View.invalidate 或 View.requestLayout 等方法更新 View 都会走到 ViewRootImpl.scheduleTraversals 方法,在这个方法中有一段代码:mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null)
,其中mChoreographer是Choreographer实例,Choreographer用来处理Vsync信号,当Vsync信号到来时,mTraversalRunnable会被执行,mTraversalRunnable是一个Runnable实例,其run方法最终会调用 ViewRootImpl.performTraversals 方法。
因此当Vsync信号来临时,会调用 ViewRootImpl.performTraversals 方法执行View的绘制流程。以startActivity为例,WindowManager.addView 添加的View是DecorView类型。以下ViewRootImpl缩写为VRImpl。
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
在一个典型的显示系统中,一般包括CPU、GPU、Display三个部分,CPU负责计算帧数据,把计算好的数据交给GPU,GPU会对图形数据进行渲染,渲染好后放到buffer(图像缓冲区)里存起来,然后Display(屏幕或显示器)负责把buffer里的数据呈现到屏幕上。
相关基础概念见Android图形系统综述。
Choreographer:编舞者,指对CPU/GPU绘制的指导,收到VSync信号才开始绘制,保证绘制拥有完整的16.6ms。通常应用层不会直接使用Choreographer,而是使用更高级的API,如View.invalidate()等,可以通过Choreographer来监控应用的帧率。
ContentProvider用于提供数据的统一访问格式,封装了底层的具体实现。对于数据的使用者来说,无需知晓数据的来源是数据库、本地文件或者网络等,使用者只需简单地使用ContentProvider提供的数据增删查改操作接口即可,基本使用可参考Android四大组件之ContentProvider。
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
广播(Broadcast)机制用于进程/线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者BroadcastReceiver便是Android四大组件之一。广播分类:
注:本文基于Android 10源码,为了文章的简洁性,引用源码的地方可能有所删减。
注:本文基于Android 9.0源码,为了文章的简洁性,引用源码的地方可能有所删减。
ServiceManager是Binder IPC通信过程中的守护进程,本身也是一个Binder服务,但并没有采用libbinder中的多线程模型来与Binder驱动通信,而是自行编写了binder.c直接和Binder驱动来通信,并且只有一个循环binder_loop来进行读取和处理事务,这样的好处是简单而高效。
ServiceManager本身工作相对简单,其功能:查询和注册服务。对于Binder IPC通信过程中,其实更多的情形是BpBinder和BBinder之间的通信,比如ActivityManagerProxy和ActivityManagerService之间的通信等。
Binder驱动的源码在Android的内核模块,Aosp源码中不包含这部分代码,可以在这里下载内核相关的源码:Kernel。Binder驱动相关的源码不大看得懂,对Linux内核了解不多,因此这篇文章借鉴了网上相关的一些解析。
Binder驱动是Android专用的,但底层的驱动架构与Linux驱动一样。binder驱动以misc设备进行注册,作为虚拟字符设备,没有直接操作硬件,只有对设备内存的处理。主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。
用户态的程序调用Kernel层驱动需要陷入内核态,进行系统调用(syscall)。比如说当用户空间调用open()方法时,通过它传入的参数:/dev/binder
,然后经过系统调用,便调用binder驱动的binder_open()方法。