2009年6月29日 星期一

Android 原始碼徹底研究系列

Android Source Code Internals

閱讀及追蹤 Android 的原始碼,是提昇你 Android 程式設計功力最好的方式之一。

可惜的是,在現今講求速食主義的年代,凡事都講求效率,大家都想直接找到解決問題的答案,而不想從打好基礎開始。別說是閱讀 Android 原始碼,連 Java 都還不會,就想一步登天的,也不在少數。以致於我看過不少,捨本逐末,事倍功半的例子。雖然你能找到解決的方法,可是在未能融會貫通的情況下,總是知其然,而不知其所以然。下次遇到類似的問題,當然還是無法自己獨立解決。

要跨入 Android 的設計殿堂,第一步是容易的。你只要會用 Eclipse 及 ADT 提供的 wizard,再加上一本範例大全在手,要寫個簡單的程式應該都不是問題。可是以這樣的經驗與訓練,要真正想要寫一個 "好" 程式,還是有很大的距離。如果你真的想要學寫一個好程式,一窺 這殿堂的奧妙之美,以我的經驗來說,還是得按部就班來,先具備一定的基礎,仍然是先決的要素。

我會建議你至少要具備以下的基礎:

  • Java core language 和 Object-Orient programming
  • 熟讀 SDK 中的 The Developer's Guide 和練習 tutorial
  • 至少要瀏覽 Android framework APIs Reference 一遍
  • 自己出些題目,練習 Android 程式
  • 在寫程式的過程中,有問題時,不要急著問,先要求自己從 The Developer's Guide 和 API Reference 中找答案

如果你已經有 OOP (C++, C# 等) 的程式設計經驗,要具備我上頭講的這些基礎,要花多久的時間?

我想為自己留三個月時間,應該就綽綽有餘。

在這些基礎都具備的情況下,想要再進一步提升你的程式設計功力,除了要想辦法讓自己多增加些程式設計經驗外,閱讀及追蹤別人寫的程式碼,更是最好的方法。不過網路上,每個人的程式功力高低不同,寫出來的程式也有好有差。讀到不良的程式,看不懂還不打緊,如果誤導你的觀念,那可就得不償失。因此,當你底子還不足以判斷好壞程式時,我會建議你直接閱讀 Android 的原始碼。根本不用捨近求遠,Android 原始碼,就是你學習 Android 程式設計時,最好的導師。

要在 Linux 中下載 Android 原始碼,應該不是問題。習慣在 Windows 下生活的你,我在 如何在 Windows 平台上下載 Android 的原始碼 中,有介紹如何在 Windows 中下載 Android 原始碼。

有了原始碼,應該從何看起,還是個問題。如果你一頭就栽進,Android framework 中的原始碼,在沒有目標與頭緒的情況下,很容易就迷失在眾多 framework 原始碼中。根據我自身的經驗,我會建議你先從 platform\packages\apps 開始,那裡面有 Android 一些內建的應用程式原始碼。像是網頁瀏覽器,計算機,鬧鐘,聯絡人,行事曆,媒體播放器,甚至於桌面程式都有。因為這些應用程式,你看得見,也摸得著,要追蹤這些的原始碼,會比較有感覺些。甚至於你還可以當場做實驗,改程式,看結果。

為了幫想要更進一步提升 Android 程式設計功力的你,在接下來的日子,我會帶領大家導讀 Android 的原始碼。想要跟隨者,先照我講的,打好你應該具備的基礎;並下載一份 Android 原始碼,到你的電腦上。

下次,我們先從 Android 的鬧鐘 (Alarm Clock) 原始碼開始看起。

15 則留言:

匿名 提到...

ysl前輩,你好:
首先,很期待之前研究Android原始碼的大作,我一直是你部落格的忠實觀眾。但針對你建議的按部就班,打下基礎的部分,有些疑惑,還請你幫忙指點。
我是去年剛進社會大學的新鮮人,在大學前,我學習程式的方法,都是一本本範例慢慢打,所以我當時寫程式幾乎都不用翻API來看,因為我的手指已經能馬上反應頭腦的想法,我也認為當時的學習方式是對的。但當我升上研究所之後,我發現我的學習方式讓我吃盡苦頭,研究所的工作量根本不能讓我慢慢的摸索新的技術,有時上禮拜討論好的東西,下禮拜就要做出來了。因此,對於寫code而言,我開始越來越依賴google,只要搜尋到我要的程式碼,就直接貼上,然後驗証修改。例如:我常在不了解C#的情況下,要寫10000行以上規模的應用程式,我也開始這樣的學習方式才是對的,畢竟,語言、平台不斷的推陳出新,好好學習怎麼設計及分析才是對未來生涯有幫助。但是,這麼的方式,我的內心還是覺得有點不踏實,好像學習的技術都不太穩固,沒有利用google搜尋程式碼,我好像就不會寫程式了。看到你對技術建議的學習方式,我開始懷疑我的做法到底對還是不對?感謝你看完我的疑惑,也請你幫我解答,我該如何面對時間及新技術對我的衝擊?謝謝
菜鳥 留

samlu 提到...

Hi 菜鳥,

我的意見還是我在文章講的那些。當程式設計基礎不札實時,每當你遇到新技術或面對新電腦語言時,自然得再花相同的時間去學習。但是當你有一定基礎與訓練時,我覺得要學習每個新技術,應該不需要太久的時間,就可以抓到重點,差別的只是需要時間來養成的熟悉度。

就以我自身的經驗來說,當時開始看 Android 時,雖然本身已是 C++/OOP 的老手,不過對 Java 這個語言還是很陌生。剛學的前幾個禮拜,還能應付自如,也寫了幾個 Android 程式。不過很快我就發覺,自身對 Java 的不熟悉,將會是我往前進步的主要障礙。

了解本身的問題,當下我就停下 Andorid 的學習,先花兩個禮拜的時間,買了本 Java 的書,將 Java 這個語言看了一遍,並對 collection, threading, interface 等用法了解清楚。我講的了解清楚,還包含了我,追蹤了幾個 collection 類別的內部實現。看完 Java 後,我又花了幾個禮拜的時間,翻了一遍 Android 的 APIs reference,期間也大量閱讀各式 Android 範例程式與原始碼。

這些基礎功都砸實了,現在寫起 Android 的程式,才能駕輕就熟,觸類旁通。就算遇到不知道的部份,我相信我也能很快理解出,如何解決的方法。那你說,我之前花的那幾個禮拜時間,值不值得?

我想寫程式,另一個重要的就是 "思考"。你要常想為什麼程式要這樣寫,這樣的程式是不是最好的,是不是有更好的解法。永遠不要滿足於你現在寫的程式,這才能幫助你更上一層樓。

寫程式的基本功札實了,接下來就是你的 Domain Knowledge 部份。所謂的 Domain Knowledge,就像你要寫網路程式,免不了要了解 HTTP 是什麼?要寫串流播放程式,就得花時間去了解 3GP, H.264 一樣。這部份學習的時間,就得端視你所在的專業領域而有所不同。

在資訊爆炸的時代,免不了你我都會有資訊恐慌的時候。囫圇吞棗,雖會解決眼前的問題,不過接之而來的消化不良,還是無法內化成為你腦袋內的東西。回歸基礎,就以我在程式領域浸淫了將近 20 多年的經驗來說,我還是覺得這是最最重要的。

千萬不要,還不會走,就想學飛了。

匿名 提到...

Hi,ysl前輩:
感謝你花這麼多我時間幫我解惑,我會重新加強我的基礎,再次感謝你的提醒,謝謝。orz

菜鳥 留

匿名 提到...

Dear Samlu:

看到您所言的, "千萬不要還不會走, 就想學飛了", 這句話, 真是讓我感觸良多呀, 之前聽到有一位學java出身的前輩, 對我說...

"都己經會飛了, 幹嘛用走的 ?"

哈...

匿名 提到...

我倒是看過很多人都“飛“得很好,但是真的不會“走路“。
寫自已的程式,都還不錯,可以執行出結果,不過經常發生意料之外的問題,而且自已還找不到,不然就是要加減功能時,還要用原來寫程式三倍以上的時間修改,因為資料結構不佳!真的飛得很好,但是經常在地上用爬的都比飛的快。

匿名 提到...

我是香港人,聽了ysl的見解,令我有很大得著,我也感覺android是易學難精,參考原始碼的應用程式實在最好的方法,我也沒想到過。

聽到ysl有這麼多時間研究,實在羡慕。可悲的是工作的時候還是得以交貨為最主要目的,至於程式的可擴展性,還是交了貨再算了。

匿名 提到...

大陆的,很关注您的blog,期待新的内容

匿名 提到...

學程式不見得要慢慢Key吧!重點還是在你對程式語言的理解!所以多看點書、文件或程式碼,要用到時你就大概知道要翻什麼api。至於android易學難精我覺得是比不上.net!另外個人覺得android文件爛到爆!!

匿名 提到...

個人也同意看原始碼是最好的學習途徑,可惜其他同事卻不這麼想。一講到要大家trace source code,幾乎每個人都面有難色,只希望有人能整理出來告訴大家。
可是時間有限,就算辦個教學討論會,也只能提幾個範例,讓他們拿這些範例去解決工作上的問題,一旦問題超出範圍或是有bug出現,往往無法自行解決。
這就好像學武功不從內功開始練,只想套幾招來應敵一樣,如果對手按招式出手還可以應付,萬一對手不按招就無法應付...,只是有感而發。

samlu 提到...

這我也有同感,多數人都想要免費的午餐。我建議就找幾個願意做的同事即可,並堅持有貢獻才能參加的作法。就差的情況,就是自己一個人trace。反正收穫都是自己的。

匿名 提到...

你好,昨天看到你的博客,关于spinner的缩小设置,真的帮助了很多。。我也是刚开始做android的项目,现在想把spinner的宽度缩小,因为显示实在是太宽了,怎么做能缩小宽度呢,最好能设置成TimePickerDialog弹出框那么大,能给我个提示吗?或者我想重写spinner,但是源码我一直没找到,能把源码的下载url告知一下吗?widget 包和app包。谢谢啦

samlu 提到...

我部落格中的這篇 http://ysl-paradise.blogspot.com/2008/10/windows-android.html 有教你如何下載原始碼。

匿名 提到...

这个我看到了也已经在下了,只是不清楚,到底哪个是app包和spinner的程序现在。。一直搞对日的,英文烂掉了

匿名 提到...

您好,請問對於 JAVA 您是否有建議的中文書?下週要去上您的課,想順便買本 JAVA 書研讀一番。

--
阿輝

samlu 提到...

Java 的書,建議先買 Java編程語言 (4th Edition) 這本,應該是碁峯出的。

張貼留言