我们首先分析RefBase类的实现原理,它的定义如下所示。
**frameworks/base/include/utils/RefBase.h**
~~~
class RefBase
{
public:
void incStrong(const void* id) const;
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type
{
public:
RefBase* refBase() const;
void incWeak(const void* id);
void decWeak(const void* id);
bool attemptIncStrong(const void* id);
//! This is only safe if you have set OBJECT_LIFETIME_FOREVER.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
protected:
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_FOREVER = 0x0003
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
virtual void onLastWeakRef(const void* id);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
weakref_impl* const mRefs;
};
~~~
与LightRefBase类一样,RefBase类也提供了成员函数incStrong和decStrong来维护它所引用的对象的引用计数。不过,RefBase类与LightRefBase类不一样,它不是直接使用一个整数来维护对象的引用计数的,而是使用一个weakref_impl对象,即成员变量mRefs来描述对象的引用计数。
weakref_impl类同时为对象提供了强引用计数和弱引用计数,它的实现如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
class RefBase::weakref_impl : public RefBase::weakref_type
{
public:
volatile int32_t mStrong;
volatile int32_t mWeak;
RefBase* const mBase;
volatile int32_t mFlags;
#if !DEBUG_REFS
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
void addStrongRef(const void* /*id*/) { }
void removeStrongRef(const void* /*id*/) { }
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
void printRefs() const { }
void trackMe(bool, bool) { }
#else
......
#endif
};
~~~
weakref_impl类继承了weakref_type类。weakref_type类定义在RefBase类的内部,它提供了成员函数incWeak、decWeak、attemptIncStrong和attemptIncWeak来维护对象的强引用计数和弱引用计数。weakref_type类只定义了引用计数维护接口,具体的实现是由weakref_impl类提供的。
weakref_impl类有两个成员变量mStrong和mWeak,分别用来描述对象的强引用计数和弱引用计数。同时,weakref_impl类的成员变量mBase指向了它所引用的对象的地址,而成员变量mFlags是一个标志值,用来描述对象的生命周期控制方式。weakref_impl类的成员变量mFlags的取值范围为0、OBJECT_LIFETIME_WEAK或者OBJECT_LIFETIME_FOREVER,其中,0表示对象的生命周期只受强引用计数影响;OBJECT_LIFETIME_WEAK表示对象的生命周期同时受强引用计数和弱引用计数影响;OBJECT_LIFETIME_FOREVER表示对象的生命周期完全不受强引用计数或者弱引用计数影响。
weakref_impl类的实现有调试和非调试两个版本,它们是通过宏DEBUG_REFS来区别的。如果定义了宏DEBUG_REFS,则weakref_impl类被编译成调试版本;否则被编译成非调试版本。weakref_impl类的调试版本只是用于调试它本身的实现,我们不关心,因此省略了这些代码。
下面我们就通过一个类图来总结RefBase、weakref_type和weakref_impl三个类的关系,如图3-1所示。
![ RefBase、weakref_type和weakref_impl类的关系](https://box.kancloud.cn/4829f723f5b3f26efd053f5d9b0e5463_631x316.jpg =631x316)
从这个类图就可以看出,每一个RefBase对象都包含了一个weakref_impl对象,而后者继承了weakref_type类。在接下来的内容中,我们会进一步介绍这三个类的作用及其关系。
强指针的实现类为sp,在前面的3.1.1小节中,我们只分析了它的轻量级指针实现。在本节中,我们将分析sp类的强指针实现,主要是分析它的构造函数和析构函数的实现。
sp类的构造函数的实现如下所示。
**frameworks/base/include/utils/RefBase.h**
~~~
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
if (other) other->incStrong(this);
}
~~~
> 注意:模块参数T是一个继承了RefBase类的子类,因此,第5行实际上是调用了RefBase类的成员函数incStrong来增加对象的强引用计数,如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->addWeakRef(id);
refs->incWeak(id);
refs->addStrongRef(id);
const int32_t c = android_atomic_inc(&refs->mStrong);
LOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
LOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
if (c != INITIAL_STRONG_VALUE) {
return;
}
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
const_cast<RefBase*>(this)->onFirstRef();
}
~~~
RefBase类的成员变量mRefs是在构造函数中初始化的,如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
// LOGV("Creating refs %p with RefBase %p\n", mRefs, this);
}
~~~
回到RefBase类的成员函数incStrong中,它主要做了三件事情:第一件事情是调用第5行代码来增加对象的弱引用计数;第二件事情是调用第8行代码来增加对象的强引用计数;第三件事情是如果发现对象是第一次被强指针引用,则第20行调用对象的成员函数onFirstRef来通知对象,它被强指针引用了,以便它可以执行一些业务相关逻辑。RefBase类的成员函数onFirstRef是一个空实现,如果子类想要处理这个事件,那么就必须要重写成员函数onFirstRef。
增加对象的弱引用计数是通过调用RefBase类的成员变量mRefs的成员函数incWeak来实现的。RefBase类的成员变量mRefs的类型为weakref_impl,它的成员函数incWeak是从父类weakref_type继承下来的,因此,它实际上是通过调用weakref_type类的成员函数incWeak来增加对象的弱引用计数的,如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->addWeakRef(id);
const int32_t c = android_atomic_inc(&impl->mWeak);
LOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
~~~
this指针指向的实际上是一个weakref_impl对象,因此,第3行将它转换为一个weakref_impl指针impl。有了这个impl指针之后,我们就可以访问它的成员变量mWeak了。第5行调用函数android_atomic_inc来增加它的成员变量mWeak的值,即增加对象的弱引用计数。第4行的函数调用是与调试相关的,我们忽略它的实现。
回到RefBase类的成员函数incStrong中,增加了对象的弱引用计数之后,接下来就调用函数android_atomic_inc来增加对象的强引用计数了,即增加RefBase类的引用计数对象mRefs的成员变量mStrong的值。函数android_atomic_inc的返回值是对象原来的强引用计数值,即加1前的值。在weakref_impl类的构造函数中,成员变量mStrong的值被初始化为INITIAL_STRONG_VALUE。INITIAL_STRONG_VALUE是一个宏,它的定义如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
#define INITIAL_STRONG_VALUE (1<<28)
~~~
从理论上说,当对象第一次被强指针引用时,它的强引用计数值应该等于1,但是我们看到,对象的强引用计数的初始值为INITIAL_STRONG_VALUE,它加1之后并不等于1,因此,RefBase类的成员函数incStrong需要将它调整为1,如第19行代码所示。
至此,强指针类sp的构造函数的实现就分析完了,它主要做的事情就是增加对象的强引用计数和弱引用计数。从这里就可以看出,虽然我们的目的是增加对象的强引用计数,但是同时也会增加对象的弱引用计数,即一个对象的弱引用计数一定是大于或者等于它的强引用计数的。
下面我们再来分析sp类的析构函数的实现,如下所示。
**frameworks/base/include/utils/RefBase.h**
~~~
template<typename T>
sp<T>::~sp()
{
if (m_ptr) m_ptr->decStrong(this);
}
~~~
前面提到,sp类的成员变量m_ptr所指向的对象是继承了RefBase类的,因此,第4行实际上是调用了RefBase类的成员函数decStrong来减少对象的强引用计数,它的实现如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = android_atomic_dec(&refs->mStrong);
#if PRINT_REFS
LOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
LOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
if (c == 1) {
const_cast<RefBase*>(this)->onLastStrongRef(id);
if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
delete this;
}
}
refs->removeWeakRef(id);
refs->decWeak(id);
}
~~~
我们忽略第4行和第16行代码,因为它们在非调试版本中是空函数调用。sp类的析构函数执行的操作刚好与构造函数相反,它主要是减少对象的强引用计数和弱引用计数。
第5行代码通过调用函数android_atomic_dec来减少对象的强引用计数。与函数android_atomic_inc类似,函数android_atomic_dec的返回值是对象原来的强引用计数值,即减1前的值,保存在变量c中。如果变量c的值等于1,就说明此时再也没有强指针引用这个对象了,因此,第11行就调用该对象的成员函数onLastStrongRef来使得它可以执行一些业务相关的逻辑,同时也要考虑是否需要释放该对象。第12行检查对象的生命周期是否受弱引用计数控制,即RefBase类的成员变量mRefs的标志值mFlags的OBJECT_LIFETIME_WEAK位是否等于1。如果不等于1,就说明对象的生命周期不受弱引用计数影响,因此,第13行就会释放对象所占用的内存,这同时会导致RefBase类的析构函数被调用。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
RefBase::~RefBase()
{
// LOGV("Destroying RefBase %p (refs %p)\n", this, mRefs);
if (mRefs->mWeak == 0) {
// LOGV("Freeing refs %p of old RefBase %p\n", mRefs, this);
delete mRefs;
}
}
~~~
在RefBase类的析构函数中,如果发现对象的弱引用计数值为0,那么就会把引用计数对象mRefs也一起释放。RefBase类的成员变量mRefs指向的是一个weakref_impl对象,它是在RefBase类的构造函数中创建的。现在既然它所属的RefBase对象已经不存在了,并且它所引用的对象的弱引用计数值也等于0,它也就不需要存在了。前面提到,一个对象的弱引用计数一定是大于等于它的强引用计数的,因此,当一个对象的强引用计数值为0时,它的弱引用计数值可能大于0。在对象的弱引用计数值大于0的情况下,我们只能将对应的RefBase对象释放掉,而不能将该RefBase对象内部的weakref_impl对象也释放掉,因为还有其他的弱指针通过该weakref_impl对象来引用实际的对象。只有当对象的弱引用计数值也为0 时,才可以将该weakref_impl对象也一起释放掉。
回到RefBase类的成员函数decStrong中,第17行代码执行减少对象的弱引用计数的操作。变量refs指向的是RefBase类内部的weakref_impl对象mRefs。weakref_impl类的成员函数decWeak是从父类weakref_type继承下来的,因此,接下来实际执行的是weakref_type类的成员函数decWeak,它的实现如下所示。
**frameworks/base/libs/utils/RefBase.cpp**
~~~
void RefBase::weakref_type::decWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
impl->removeWeakRef(id);
const int32_t c = android_atomic_dec(&impl->mWeak);
LOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
if (c != 1) return;
if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {
if (impl->mStrong == INITIAL_STRONG_VALUE)
delete impl->mBase;
else {
// LOGV("Freeing refs %p of old RefBase %p\n", this, impl->mBase);
delete impl;
}
} else {
impl->mBase->onLastWeakRef(id);
if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {
delete impl->mBase;
}
}
}
~~~
第4行的函数调用在非调试版本中是空函数调用,我们将它忽略。第5行调用android_atomic_dec函数来减少对象的弱引用计数,并且返回减少之前的值,保存在变量c中。如果c的值不等于1,那么就说明还有其他的弱指针在引用这个对象,因此,就不用进一步处理了;如果c的值等于1,那么就说明再也没有弱指针引用这个对象了,同时也说明没有强指针引用这个对象了,因为当对象的弱引用计数值等于0时,它的强引用计数值也一定等于0。在对象的弱引用计数值等于0时,我们就要考虑是否需要将该对象释放掉。这取决于对象的生命周期控制方式,以及该对象是否被强指针引用过。下面我们分为两种情况来考虑。
第一种情况是对象的生命周期只受强引用计数控制,即第9行的if语句为true。此时如果第10行的if语句也为true,即对象从来没有被强指针引用过,那么在该对象的弱引用计数值等于0时,第11行就需要将该对象释放掉;否则,这个对象以后就会得不到释放。当一个只受强引用计数控制的对象只被弱指针引用时,就会出现这种情况。如果对象的生命周期只受强引用计数控制,并且它也被强指针引用过,那么在该对象的弱引用计数值变为0时,该对象就已经在RefBase类的成员函数decStrong中被释放,因此,第14行只负责释放其内部的引用计数器对象weakref_impl。
第二种情况是对象的生命周期受弱引用计数控制,即第9行的if语句为false。第17行首先调用对象的成员函数onLastWeakRef来使得它可以执行一些业务相关的逻辑,同时也要考虑是否需要将该对象释放掉。第18行检查对象的生命周期是否完全不受强引用计数和弱引用计数控制,即RefBase类的成员变量mRefs的标志值mFlags的OBJECT_LIFETIME_FOREVER位是否等于1。如果不等于1,那么第19行就会释放对象所占用的内存。
从第二种情况就可以看出,当对象的生命周期控制标志值设置为OBJECT_LIFETIME_FOREVER时,即对象的生命周期完全不受强引用计数和弱引用计数控制时,Android系统所提供的智能指针就退化成一个普通的C++指针了,这时候开发人员就需要手动地释放那些不再使用了的对象所占用的内存。
至此,强指针的实现原理就分析完了。为了加深对它的理解,我们对对象的生命周期控制方式作一个小结。
(1)如果一个对象的生命周期控制标志值被设置为0,那么只要它的强引用计数值为0,系统就会自动释放这个对象。
(2)如果一个对象的生命周期控制标志值被设置为OBJECT_LIFETIME_WEAK,那么只有当它的强引用计数值和弱引用计数值都为0时,系统才会自动释放这个对象。
(3)如果一个对象的生命周期控制标志值被设置为OBJECT_LIFETIME_FOREVER,那么系统就 永远不会自动释放这个对象,它需要由开发人员来手动地释放。
接下来,我们继续分析弱指针的实现原理。
- 文章概述
- 下载Android源码以及查看源码
- win10 平台通过VMware Workstation安装Ubuntu
- Linux系统安装Ubuntu编译Android源码
- Eclipse快捷键大全
- 前言
- 第一篇 初识Android系统
- 第一章 准备知识
- 1.1 Linux内核参考书籍
- 1.2 Android应用程序参考书籍
- 1.3 下载、编译和运行Android源代码
- 1.3.1 下载Android源代码
- 1.3.2 编译Android源代码
- 1.3.3 运行Android模拟器
- 1.4 下载、编译和运行Android内核源代码
- 1.4.1 下载Android内核源代码
- 1.4.2 编译Android内核源代码
- 1.4.3 运行Android模拟器
- 1.5 开发第一个Android应用程序
- 1.6 单独编译和打包Android应用程序模块
- 1.6.1 导入单独编译模块的mmm命令
- 1.6.2 单独编译Android应用程序模块
- 1.6.3 重新打包Android系统镜像文件
- 第二章 硬件抽象层
- 2.1 开发Android硬件驱动程序
- 2.1.1 实现内核驱动程序模块
- 2.1.2 修改内核Kconfig文件
- 2.1.3 修改内核Makefile文件
- 2.1.4 编译内核驱动程序模块
- 2.1.5 验证内核驱动程序模块
- 2.2 开发C可执行程序验证Android硬件驱动程序
- 2.3 开发Android硬件抽象层模块
- 2.3.1 硬件抽象层模块编写规范
- 2.3.1.1 硬件抽象层模块文件命名规范
- 2.3.1.2 硬件抽象层模块结构体定义规范
- 2.3.2 编写硬件抽象层模块接口
- 2.3.3 硬件抽象层模块的加载过程
- 2.3.4 处理硬件设备访问权限问题
- 2.4 开发Android硬件访问服务
- 2.4.1 定义硬件访问服务接口
- 2.4.2 实现硬件访问服务
- 2.4.3 实现硬件访问服务的JNI方法
- 2.4.4 启动硬件访问服务
- 2.5 开发Android应用程序来使用硬件访问服务
- 第三章 智能指针
- 3.1 轻量级指针
- 3.1.1 实现原理分析
- 3.1.2 使用实例分析
- 3.2 强指针和弱指针
- 3.2.1 强指针的实现原理分析
- 3.2.2 弱指针的实现原理分析
- 3.2.3 应用实例分析
- 第二篇 Android专用驱动系统
- 第四章 Logger日志系统
- 4.1 Logger日志格式
- 4.2 Logger日志驱动程序
- 4.2.1 基础数据结构
- 4.2.2 日志设备的初始化过程
- 4.2.3 日志设备文件的打开过程
- 4.2.4 日志记录的读取过程
- 4.2.5 日志记录的写入过程
- 4.3 运行时库层日志库
- 4.4 C/C++日志写入接口
- 4.5 Java日志写入接口
- 4.6 Logcat工具分析
- 4.6.1 基础数据结构
- 4.6.2 初始化过程
- 4.6.3 日志记录的读取过程
- 4.6.4 日志记录的输出过程
- 第五章 Binder进程间通信系统
- 5.1 Binder驱动程序
- 5.1.1 基础数据结构
- 5.1.2 Binder设备的初始化过程
- 5.1.3 Binder设备文件的打开过程
- 5.1.4 设备文件内存映射过程
- 5.1.5 内核缓冲区管理
- 5.1.5.1 分配内核缓冲区
- 5.1.5.2 释放内核缓冲区
- 5.1.5.3 查询内核缓冲区
- 5.2 Binder进程间通信库
- 5.3 Binder进程间通信应用实例
- 5.4 Binder对象引用计数技术
- 5.4.1 Binder本地对象的生命周期
- 5.4.2 Binder实体对象的生命周期
- 5.4.3 Binder引用对象的生命周期
- 5.4.4 Binder代理对象的生命周期
- 5.5 Binder对象死亡通知机制
- 5.5.1 注册死亡接收通知
- 5.5.2 发送死亡接收通知
- 5.5.3 注销死亡接收通知
- 5.6 Service Manager的启动过程
- 5.6.1 打开和映射Binder设备文件
- 5.6.2 注册成为Binder上下文管理者
- 5.6.3 循环等待Client进程请求
- 5.7 Service Manager代理对象接口的获取过程
- 5.8 Service的启动过程
- 5.8.1 注册Service组件
- 5.8.1.1 封装通信数据为Parcel对象
- 5.8.1.2 发送和处理BC_TRANSACTION命令协议
- 5.8.1.3 发送和处理BR_TRANSACTION返回协议
- 5.8.1.4 发送和处理BC_REPLY命令协议
- 5.8.1.5 发送和处理BR_REPLY返回协议
- 5.8.2 循环等待Client进程请求
- 5.9 Service代理对象接口的获取过程
- 5.10 Binder进程间通信机制的Java实现接口
- 5.10.1 获取Service Manager的Java代理对象接口
- 5.10.2 AIDL服务接口解析
- 5.10.3 Java服务的启动过程
- 5.10.4 获取Java服务的代理对象接口
- 5.10.5 Java服务的调用过程
- 第六章 Ashmem匿名共享内存系统
- 6.1 Ashmem驱动程序
- 6.1.1 相关数据结构
- 6.1.2 设备初始化过程
- 6.1.3 设备文件打开过程
- 6.1.4 设备文件内存映射过程
- 6.1.5 内存块的锁定和解锁过程
- 6.1.6 解锁状态内存块的回收过程
- 6.2 运行时库cutils的匿名共享内存接口
- 6.3 匿名共享内存的C++访问接口
- 6.3.1 MemoryHeapBase
- 6.3.1.1 Server端的实现
- 6.3.1.2 Client端的实现
- 6.3.2 MemoryBase
- 6.3.2.1 Server端的实现
- 6.3.2.2 Client端的实现
- 6.3.3 应用实例
- 6.4 匿名共享内存的Java访问接口
- 6.4.1 MemoryFile
- 6.4.2 应用实例
- 6.5 匿名共享内存的共享原理分析
- 第三篇 Android应用程序框架篇
- 第七章 Activity组件的启动过程
- 7.1 Activity组件应用实例
- 7.2 根Activity的启动过程
- 7.3 Activity在进程内的启动过程
- 7.4 Activity在新进程中的启动过程
- 第八章 Service组件的启动过程
- 8.1 Service组件应用实例
- 8.2 Service在新进程中的启动过程
- 8.3 Service在进程内的绑定过程
- 第九章 Android系统广播机制
- 9.1 广播应用实例
- 9.2 广播接收者的注册过程
- 9.3 广播的发送过程
- 第十章 Content Provider组件的实现原理
- 10.1 Content Provider组件应用实例
- 10.1.1 ArticlesProvider
- 10.1.2 Article
- 10.2 Content Provider组件的启动过程
- 10.3 Content Provider组件的数据共享原理
- 10.4 Content Provider组件的数据更新通知机制
- 10.4.1 内容观察者的注册过程
- 10.4.2 数据更新的通知过程
- 第十一章 Zygote和System进程的启动过程
- 11.1 Zygote进程的启动脚本
- 11.2 Zygote进程的启动过程
- 11.3 System进程的启动过程
- 第十二章 Android应用程序进程的启动过程
- 12.1 应用程序进程的创建过程
- 12.2 Binder线程池的启动过程
- 12.3 消息循环的创建过程
- 第十三章 Android应用程序的消息处理机制
- 13.1 创建线程消息队列
- 13.2 线程消息循环过程
- 13.3 线程消息发送过程
- 13.4 线程消息处理过程
- 第十四章 Android应用程序的键盘消息处理机制
- 14.1 InputManager的启动过程
- 14.1.1 创建InputManager
- 14.1.2 启动InputManager
- 14.1.3 启动InputDispatcher
- 14.1.4 启动InputReader
- 14.2 InputChannel的注册过程
- 14.2.1 创建InputChannel
- 14.2.2 注册Server端InputChannel
- 14.2.3 注册当前激活窗口
- 14.2.4 注册Client端InputChannel
- 14.3 键盘消息的分发过程
- 14.3.1 InputReader处理键盘事件
- 14.3.2 InputDispatcher分发键盘事件
- 14.3.3 当前激活的窗口获得键盘消息
- 14.3.4 InputDispatcher获得键盘事件处理完成通知
- 14.4 InputChannel的注销过程
- 14.4.1 销毁应用程序窗口
- 14.4.2 注销Client端InputChannel
- 14.4.3 注销Server端InputChannel
- 第十五章 Android应用程序线程的消息循环模型
- 15.1 应用程序主线程消息循环模型
- 15.2 界面无关的应用程序子线程消息循环模型
- 15.3 界面相关的应用程序子线程消息循环模型
- 第十六章 Android应用程序的安装和显示过程
- 16.1 应用程序的安装过程
- 16.2 应用程序的显示过程