1. 程式人生 > >如何快速閱讀並分析Android原始碼

如何快速閱讀並分析Android原始碼

很多時候為了解決一個問題必須先理解Android系統的執行原理,這時候就得閱讀應用層框架的原始碼。學會閱讀系統原始碼或者他人的程式碼,這是研發必備的技能之一,只有瞭解別人寫的東西才能在他之上更好的行事,同時也能去學習和借鑑他人優秀的程式碼思想。

那麼,如何閱讀並分析Android原始碼呢?

這裡我只講一些初級的、基礎的方法,很快就可以上手,不需要下載和編譯系統原始碼。

我們下載Android SDK的時候一般都會下載相應版本的原始碼(sdk/sources目錄下),在AS(Android Studio)上追蹤系統程式碼時會自動開啟原始碼檔案,如果沒有原始碼則會提示下載:


系統的原始碼一般多且複雜,雖然有不少註釋,但如果純靠閱讀去理解會相當吃力,很難把握整體流程。我們需要結合實際使用場景,通過debug去分析程式碼的執行邏輯。那麼SDK的版本有那麼多,應該檢視哪個版本的原始碼呢?這個根據需要,如果要檢視最新7.0的原始碼就檢視相應的。如果沒有指定的版本,一般你開啟的SDK自帶的虛擬機器的版本是多少就檢視相應版本的程式碼。我們可以通過在專案build.gradle檔案裡面配置compileSdkVersion為指定的版本

,這樣在AS上追蹤程式碼時跳轉的即是對應版本的原始碼檔案。(這裡我強調的是自帶的虛擬機器,而不是真機或其他第三方的虛擬機器。因為自帶的虛擬機器的rom可以保證程式碼是沒有修改過的,跟官方原始碼的行數可以對得上。)

例如,一般情況下,我使用版本22的虛擬機器:


接著把專案的compileSdkVersion配置為22:

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.0"
    ...
}

然後在AS上追蹤系統程式碼,或者通過雙擊shift鍵,輸入需要查詢的系統類:



我們可以看到這時候的原始碼版本都是android-22。

接下來我們就要根據使用場景,尋找一個入口的地方,打一個斷點,同時在其他覺得可疑的關鍵地方也打入斷點,進入debug模式,這樣邏輯就會在斷點的地方停止,這時候就可以檢視程式碼的執行邏輯,藉助AS強大的debug功能分析程式碼。debug一定要有耐心,而且要多嘗試設定可疑斷點,讓程式碼在關鍵地方停止。多運用幾次就可以快速閱讀和分析系統原始碼,明白其中的程式碼邏輯。

這裡給個建議,一開始只需要把握某一個功能的整體程式碼邏輯,設定幾個關鍵斷點,通過斷點閱讀程式碼,不要深入細節無法自拔。等理解了整體邏輯之後,再考慮從細節地方入手,一句句程式碼debug下去。

最後,我們通過一個實際場景運用上面的方法去分析"View的OnClickListener.onClick()方法是怎樣被觸發的"。

首先新建一個專案,build.gradle裡的配置如下:

android {
    compileSdkVersion 22
    ...
}

建立一個頁面,裡面存在一個按鈕,設定了OnClickListener,啟動自帶的api版本為22的虛擬機器,執行專案,效果如下:


那麼接下來debug從哪裡入手呢?我們並不知道OnClickListener在哪裡被回撥,因此並不能預先在系統程式碼裡打斷點。這裡我們可以觀察呼叫view.setOnClickListener()的程式碼,然後檢視OnClickListener物件儲存在哪,什麼時候呼叫,然後在關鍵地方打入斷點。但其實還有更簡單的方法,我們採用逆向思維,直接在OnClikcListener.onClick()方法裡面打入斷點:


進入debug模式:


點選按鈕,然後程式碼會執行到斷點的地方,這個時候我們檢視左下角呼叫棧:


可以看到onClick方法是被View.performClick()方法呼叫,繼續下檢視呼叫棧發現performClick方法又是在PerformClick物件中執行:


PerformClick物件實現了Runnable,run()方法是在主執行緒訊息佇列執行的,所以接下來我們需要在View的原始碼裡追蹤程式碼,藉助AS強大的功能檢視PerformClick物件哪裡被建立和被呼叫:


從上面可以看出關鍵地方,PerformClick在View.onTouchEvent()方法被呼叫。想必接下來要分析"View的OnClickListener.onClick()方法是怎樣被觸發的"這個問題就知道如何下手了,比如我們可以在View.onTouchEvent()打入斷點,一步步程式碼檢視具體的程式碼邏輯:


整個的過程大概就這樣,當然不同問題要靈活處理,重要的是多實踐多操作,就會得出一套自己解決問題的方法。