我們首先分析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_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 應用程序的顯示過程