1. 程式人生 > >Android Framework 如何學習,如何從應用深入到Framework?

Android Framework 如何學習,如何從應用深入到Framework?

猶豫了整整兩天要不要寫這個,覺得還是分享一下自己覺得高效又無痛的方法罷。

首先放個地圖炮,任何光講原始碼的書都是耍流氓,無一例外。作者或許是大神,或許對於每一個地方的每一處原始碼都爛熟於心,但並不代表他們可以寫出一部好書。原因很多時候在於,Android的功夫,在Android之外。這是理解Android原始碼的“道”,也是我近幾年來愈發強烈的感受。

至於“術”,我只想說大神部落格也好,書也好,90%的講述方式都是錯誤的——作者展示出Android原始碼,然後告訴你這段是幹嘛的,然後下一段……這樣的書或部落格,我個人看得非常痛苦,一開始我不明白為什麼,工作了第三年,猛然明白,讀起來痛苦的原因是倒轉了因果。

幾乎所有程式碼or模組or系統的開發初衷,都是為了解決某一問題。如果你光看原始碼,哦這個是幹嘛的,那裡呼叫了哪個API,這樣看毫無意義,這樣的所謂“講解”書也毫無意義。大把的《深入XXX》實際上都沒有深入,因為他們並沒有搞清或說清,這裡有個什麼樣的問題,而這個部分模組or原始碼怎樣解決了這個問題,以及曾經其餘的系統上如何解決這個問題——更有甚者,他們講完解決方案,然後再編個問題出來,且說的好像這個問題只有這唯一一種方案可解一樣……

就比如Binder機制,所有人都能說出來它是跨程序通訊用的,可是你依然會看得想要吐血。包括很多blog講起這部分,都有一種先有答案後編個問題出來的嫌疑,理解並不深入(尤其是上來就將Media部分的,大部分根本只講了“怎麼用”,完全沒有“為什麼”的部分,這也好意思起名字叫“深入理解XXX”)。

你想搞明白,首先要忘了Binder。然後想想看,有什麼樣的方案實現一個跨程序通訊的方式?最容易想到的,一個是“共享記憶體”的方式或是“共享磁碟檔案”的方式。其餘的方式呢?

想不到去看看舊有的Linux系統上的演變過程,當你看到管道(Pipe)方式的實現,就會開始恍然大悟——原來還可以通過這樣。然後你會更加理解UDS(Unix Domain Socket,非TCP/IP裡面的那個socket,很多人會困惑與此)的出現,此刻你心裡對於Server-Client端互相建立起IPC連結的過程才將變得明朗,甚至可以推出RPC(Remote Procedure Calls)的實現模型。

到這裡,你再去看Binder的實現,從巨集觀的模型開始,一切都變得異常清晰起來。對於Binder Client和Binder Service各自的角色有了理解,Binder驅動與ServiceManager的聯動,就變得更加清楚——和UDS或者RPC是不是很類似?甚至更容易理解一些,如果更加抽象的形容,ServiceManager就像DNS一樣,負責Client查詢到BinderService的IP地址(這也就理解了為何ServiceManager的通訊標誌恆為0),而Binder驅動則是路由器的角色。

然後細化下去,針對每一個模組本身的職責,詢問更細節的實現,永遠記住,先有的問題,之後才有的程式碼——這樣才能理解為何Parcel是必要的(跨程序通訊的高效序列化資料載體),為何IBinder或BpBinder是必須的,AIDL又是什麼用——程式碼實現是新鮮的,但是有了之前的鋪墊和對問題的預期,它們的出現才是可理解的。這是理解Android原始碼之“術”。

當然,說起來容易,做起來難

整套模組看下來,拋開資訊檢索能力不談,你需要補一些C++的基礎,需要補計算機系統的基礎,甚至需要理解設計模式——但不是說你成為任何一方的專家才能理解,只是隨著一點點深入問題,隨時去補課罷了。所以說跳著看書的能力是必須的,不是你想不想或者喜不喜歡的問題,它就是必須的——你唯一的問題就是願不願意讓自己適應它,還是找個藉口繞路。

所以這個問題又回到了最初提出的觀點——Android的功夫,在Android之外。你要想“理解”而非單純的“知道”,想“學習”而非單純的“記誦”,我覺得沒有他路可走。

總結起來就是:
  • 先理解模組對應的要解決的“問題”是什麼,再去給問題找解決方案的思路去理解原始碼。
  • 理解原始碼的功夫不止在Android本身,也要提高Android之外的知識水平。

最後,繼續鄙視那些玩了幾個app、聽說Android開發語言用Java就對Android嗤之以鼻的自大狂們——對於Android這個龐大的知識庫來說,90%的人離入門都還差得遠呢。