Android 程式設計
新版 Android SDK 下載安裝中文教學課程講義,歡迎延伸點閱!
我們的《Android 手機應用程式開發教學課程免費講義》網路讀者俱樂部會員(請點選此連結),歡迎您的加入,謝謝!
本講義目前網路連載發表有:Android手機程式開發教學講義懶人包、Android 教學講義第一講、Android 教學講義第二講、Android 教學講義第三講、Android 教學講義第四講、Android 教學講義第五講、Android 教學講義第六講、Android 教學講義第七講上篇、Android 教學講義第七講下篇、Android 2.3補充教材1、Android 2.3補充教材2、Android 3.0平板電腦完整功能搶先看(From T-Mobile)、Android 3.0 平板電腦應用程式開發:第一講、Android 3.0 SDK 正式版登場、Android 嵌入式系統最新開發應用 - SAAB IQon 車用電腦、Android 2.3 補充教材3、Android 3.0 平板電腦應用程式開發:第二講、Android 教學講義第八講上篇、Android 教學講義第八講中篇(1)、Android 4.0 SDK 開發功能介紹與下載網址、 Android 4.0 SDK 下載安裝完整教學、 Android 4.0 模擬器安裝設定教學課程講義、Android 4.0 的 Holo theme 佈景主題介紹與設定教學課程講義、Android 4.2 升級功能簡介、Android 4.2 SDK & ADT Bundle 下載安裝教學、2013年第1講: Android Application Project 之建立、2013年最新 Android Studio 開發工具下載安裝教學、最新 Android App 網路連線程式設計範例 (第一講) - Volley HTTP Library 入門教學、Android App 與 Android Application Project 是什麼?、Android 4.4 KitKat 與 Android 4.4 SDK 開發功能介紹、Android SDK 下載安裝中文教學課程講義 ( 2013年11月新版,ADT Bundle )
以下為本篇 Android 教學講義的開始。
在上回我們的Android課程教學講義-第六講之中,我們已運用”Converter應用程式”之Android UI介面設計實例教學,跟大家說明如何透過Eclipse來進行Android手機的介面設計工作。不知您是否已經開始動手操作看看了嗎?
接下來,此次講義仍將以”Converter應用程式”為例,教大家如何在Eclipse裡頭進行Android手機應用程式的Java程式設計工作。
以下,我們會以相當完整且詳細的篇幅為大家深入探究”Converter應用程式”當中的每一段Java程式碼之意義與源由。
本講義希望藉此幫助身為Android手機應用程式初學者的您,更進一步地暸解Android手機應用程式的Java程式設計內涵。
另外,礙於第七講全文的篇幅過長之故,因此,本講義將第七講分成上、下兩篇發表。此次發表的是第七講的上篇,主要是詳解Android最初所預設的十一行Java程式碼。
以下為本次第七講(上篇)的十二項主軸:
- Android程式設計:什麼是Activity應用程式組件?
- Android程式設計:使用Eclipse開始進行Anodrid的Java程式設計
- Android程式設計:[package]建立應用程式的Java類別套件
- Android程式設計:[import]連結存取其它必要的Java類別套件
- Android程式設計:初探物件導向程式設計
- Android程式設計:[class]宣告Android手機應用程式的主類別
- Android程式設計:建立文字註釋說明
- Android程式設計:建立應用程式的API說明文件
- Anodrid程式設計:建立@Override的Annotation註釋
- Android程式設計:覆寫Activity類別的onCreate(bundle)方法
- Android程式設計:重新呼叫Activity類別的onCreate(bundle)方法
- Android程式設計:呼叫Activity類別的setContentView(int)方法
如果您是初次閱讀本講義教材者,為求學習之完整性,因此煩請您先從本講義之第一講、第二講、第三講、第四講、第五講與第六講開始閱讀,謝謝!
Android程式設計:什麼是Activity應用程式組件?
【孫傳雄研究室 編著】Android手機應用程式大致上可以分成四種組件(Application Components),分別為Activity、Services、Broadcast receivers與Content providers。這四種組件並非完全獨立存在,常需依不同的需求狀況混合運用。(註:此四種應用程式組件的異同,將在本講義第八講詳述。)
由於,只要是應用程式需提供手機畫面給手機用戶操縱的狀況下,皆要以Activity應用程式組件達成。所以,Activity應用程式組件可謂是Android手機應用程式四大組件之基石。
因為,Activity應用程式組件主宰了Android手機應用程式的使用者介面(User Interface, UI)之相關程式運算工作,因此,它頗像是傳統程式設計常提及的前端(Front End)應用程式,
當然,Android手機應用程式的執行環境是在Android智慧型手機之上,而非個人電腦。因此,Activity應用程式組件仍有些極為特殊之處:例如,Activity應用程式組件沒有傳統Java應用程式啟始點的main()方法,取而代之是Activity生命週期的概念。(註:關於此部份,我們會在日後的講義中,陸續深入探究。)
Android程式設計:使用Eclipse開始進行Anodrid的Java程式設計
由於,本講義的”Converter應用程式”教學實例也是Activity應用程式組件的應用,所以,我們將此教學實例分成介面設計與程式設計兩篇講義深入論述。
當您按著我們在先前第六講所描述的步驟,完成”Converter應用程式”使用者介面之設計後。在本次講義當中,我們要教您開始使用Eclipse進行”Converter應用程式”當中的Java程式設計工作。
由於,Android手機應用程式是使用Java程式語言進行程式的設計,因此,有些初學者常擔心自己並不熟悉Java程式語言,而會造成學習Android手機應用程式開發的障礙。
本講義要建議這些對Java程式語言不熟悉的讀者,您們不妨把Android手機應用程式的學習也當作精進Java程式設計能力的一種管道。
因為,大部份Java程式語言的語法運用,也可以從Android手機應用程式的實作當中開始學習。所以,兩者並無彼此完全互斥與衝突之處。
不過,礙於Android手機應用程式的架構仍和Java應用程式有些許不同之處,因此,您若需專注開發傳統的Java應用程式,我們仍建議您要從正統的Java程式語言學起。
至如,如何開始進行本講義之”Converter應用程式”的程式設計工作呢?
在此,請您先完成第六講所述之步驟,然後,至Eclipse主畫面中的”Project Explorer”子視窗之”Converter”專案名稱下,開啟”Converter.java”檔案。它的檔案路徑是在”src”目錄之下(如下圖箭頭指引處所示)。
當開啟”Converter.java”檔案後,您會發現檔案裡頭已有十一行的Java程式碼。
這十一行的Java程式碼是Android系統所預設的。
此程式碼主要目的是協助應用程式的使用者介面能夠順利地顯示於手機的螢幕之中。
這也就是說,即使您在建立”Converter應用程式”專案後,什麼事都沒做。此Java檔案仍具有在手機螢幕上顯示預設使用者介面的作用。(註:即Android預設的”Hello, World”使用者介面)
另外,您會發現在”Converter.java”檔案子視窗的左側有”+”與”-”的按鈕。這些按鈕具有將相關性的程式碼收納成一行或恢復成多行的用途。(註:按下”+”按鈕是打開,按下”-”按鈕是收納。)
由於,Eclipse為了讓程式碼看起來更簡約,因此,提供此程式碼的收納功能。
程式開發者可以將一些已撰寫好且具相關性的程式碼,先收納成一行,讓檔案子視窗看起來不致於太過雜亂。
如果要將收納成單行的程式碼恢復原狀,您可依下列步驟達成。
例如,因為,Android預設程式碼的第二行與第三行都是import相關的程式碼,因此,它們被預設成只顯示第二行。
此時,您可以按下”+”按鈕,便可以將第三行一同顯示出來。
以下為恢復之後的原狀。
若您再按下”-“按鈕則又會收納成一行程式碼。
此外,有些程式開發者習慣在撰寫程式時,能夠有程式碼行號的對照輔助。
在Eclipse當中有提供顯示程式碼行號的功能。
至於,怎麼做呢?
您可以將滑鼠游標移至”Converter.java”檔案子視窗的左側,並且按下滑鼠右鍵。
當出現彈出式對話方塊時,將”Show Line Numbers”選項打勾即可顯示程式碼行號(如下圖箭頭1處、箭頭2處所示)。
接下來,我們便要開始為您逐行解釋Converter應用程式當中所有程式碼的意義與用法。
在此要特別強調地是,以下講義內容會先從Android所預設的十一行程式碼解說開始,然後再逐步地推演至全部Converter應用程式的程式碼解說。
同時,我們會在每一行程式碼解說文字上面,置放本講義實際在Eclipse當中操作的程式碼擷取畫面,以供您對照實作。
Android程式設計:[package]建立應用程式的Java類別套件
我們在Android課程教學講義-第五講當中已提過:
『Java程式語言為了讓應用程式之間彼此不衝突,因此設置了套件(Package)的機制。
每一個Java應用程式都需要取一個獨特且唯一的套件名稱,以方便識別與呼叫取用。
Android手機應用程式在此的命名規則與其它Java應用程式的套件名稱(Package name)一致。
亦即您只能使用小寫英文字母命名,並且至少要以兩個英文單字組成,每個英文單字之間以 . 做為間隔。這個以專業術語來說,就是該名稱要為域名格式(domain-style)。』
所以,當人們在建立Android手機應用程式專案之初,便必需設定套件名稱(Package name)。
隨後,Android會在該專案的”src”檔案目錄之下,將這個名稱建立成實體的檔案目錄路徑,藉以存放Android手機應用程式的Java原始程式檔案(*.java)。
例如,套件名稱若為“tw.gururu.converter”,則Android開發工具會在專案的”src”檔案目錄之下,將此名稱的三個英文單字拆解並建立成具階層性的子目錄,亦即 tw > gururu > converter。(如下圖紅框處所示,Android手機應用程式的專案檔案目錄結構請參見本課程教學講義的第五講)
不過,上述只是設定Android手機應用程式專案之程式碼的實體檔案目錄路徑。
此外,您仍需要回到Java程式碼開頭指定該套件名稱,藉以在Android手機應用程式被Java程式語言編譯器編譯時,亦能夠採取此種目錄路徑原則儲存編譯好的.class類別檔案。
然而,請不用擔心,Android早已把這部份的程式碼預設好了!
比如,本講義之”Converter應用程式”的Java程式碼開頭,便預設了下列程式碼:
package tw.gururu.converter;
以下則為該程式碼的補充說明。
- package關鍵詞:”package”關鍵詞用於告知Java程式語言編譯器在編譯該應用程式時,拆解套件名稱並在專案的”bin”子目錄中建立以此名稱為主的階層性子目錄,且將其所編譯完成的.class檔案放置到該階層性子目錄之最後的那個目錄。
比如,”Converter應用程式”的.class檔案便被放置到 bin > tw > gururu > converter 檔案目錄的路徑之下。(如下圖紅框處所示,Android手機應用程式的檔案產生過程請參見本課程教學講義的第二講)
- ; 分號:另外,您會看到該行程式碼的結尾有一個分號。
由於,Java程式語言當中,除了類別、方法的宣告以及註釋之外,每一行程式碼的最後面皆要加一個分號,以示該行程式碼到此為止。因此,此行程式碼才會有分號的出現。
Android程式設計:[import]連結存取其它必要的Java類別套件
接續在Android預設程式碼的第一行之後,則是負責連結存取其它必要的Java類別套件的程式碼。
Android先預設了兩行如下:
import android.app.Activity;
import android.os.Bundle;
以下則為該程式碼的補充說明。
- import關鍵詞:當您在開發Android手機應用程式時,Java程式碼並不可能從零開始,全部自行撰寫。
有許多時候,必需要連結存取其它的Java類別套件(Package)。
所以在Android預設程式碼的第二行與第三行,便是透過”import”關鍵詞來連結存取兩個android最重要的官方套件,分別為”android.app.Activity”與”android.os.Bundle”。
您可能會有個疑問:『這兩個Android官方套件是從那裡來的呢? 』
其實,這兩個官方套件在Android手機應用程式的開發過程中,被存放在Android SDK檔案路徑下的”android.jar”壓縮檔案。(註:.jar檔案格式全名為Java Archive,為Java程式開發者利用JDK所提供的JAR檔案壓縮工具(jar.exe),將多個Java類別檔案(.class)壓縮後的檔案格式。)
這個壓縮檔案裡頭包含了許多以.class類別檔案為主的Android系統函式庫(Libraries)。
當然,它會依您當初在建置Android手機應用程式專案時,所設定的Build Target之Android API版本而有所不同。
比如,在”Converter應用程式”中所設定的Build Target是Android 2.1 API版本,所以,它所連結存取的Android系統函式庫也會是Android 2.1的版本(如下圖箭頭指引處所示)。
您之後在撰寫Android手機應用程式的Java程式碼時,會經常透過”import”關鍵詞來連結存取Android系統函式庫之中的類別套件。
至於,”android.app.Activity”與”android.os.Bundle”這兩個類別套件分別代表什麼作用呢?本講義分述如下:
- android.app.Activity:由於,建立”Converter應用程式”專案之初,您已勾選了”Create Activity”選項。因此,”Converter應用程式”會被設定成一個具有使用者介面(User Interface, UI)的”Activity應用程式組件”型態。
至於,什麼是”Activity”呢?本講義的第八講會詳細進行說明。
您目前可先初略知道:”Activity”是開發Android手機應用程式最主要的四種組件之一,它肩負了與使用者互動的相關程式運作。而”android.app.Activity”類別套件便是提供了Activity生命週期(Lifecycle)的各階段,它所需的主要函式方法。所以,在Java程式碼的第二行宣告連結存取該類別套件。
- android.os.Bundle:”android.os.Bundle”類別套件主要負責在不同的”Activity”程式間傳遞參數內容的工作。在接下來程式碼中的”onCreate(bundle)”方法中會需要用到此類別套件,因此,在Java程式碼的第三行先宣告連結存取該類別套件。
說到此處,您可能會有個疑問:『我要如何知道該”import”那些類別套件呢 ?』此部份,在本講義的下篇會清楚說明。
Android程式設計:初探物件導向程式設計
由於,Java是物件導向(Object-oriented, OO)的程式語言,因此,它的觀念皆源於物件導向程式設計(Object-oriented programming)的方法論。
至於,什麼叫物件導向程式設計呢?簡單地說,就是將所有的程式以物體(又稱物件,Object)的抽象化概念去比擬。
為了讓初學者能比較容易地理解物件導向的觀念,因此,我們以真實世界為例,初步地描述物件導向程式設計的六個重點要素。
- 物件:什麼是物件呢?英文稱為Object,它指的其實就是物體。
我們可以把所有程式碼想像成真實世界當中各種有形的生物或非生物。這些物體都具有相貌、而且也擁有各自的作用與價值。
當然,就物件導向程式設計的角度來看,程式開發者在程式碼中創造了許許多多不同的軟體物件,一個按鈕是一個物件、一個下拉式選單也是一個物件。
因為,它們各自具有不同的功能並可同時結合在一個應用程式之中。因此,這些物件也發揮了各自的作用與價值。
- 物件的屬性與方法:這些物體的相貌與作用,若以物件導向程式設計的專業術語來說:即是物件的屬性(Attribute)與方法(Method)。
好比,做為一個人,我們有外貌、體格,這是人表現於外的”屬性”。
另外,我們能夠運用身體去行走、去說話、去聆聽外界的聲音,這是人生存在這世界上的”方法”。
反觀於物件導向程式設計當中的物件來看。
一個按鈕有長度、寬度、文字或者顏色等屬性。
當使用者按下它時,因為程式開發者已為它賦予表現的方法,因此它會依這個方法,發揮其存在的作用與價值。
比如,按鈕被按下後,即馬上顯示圖片。此觸發動作就是執行方法後的作用。
- 物件的類別:當然,這些具有共同相貌與作用特徵的物體,人們總喜歡將它們進行抽象的分類,以便識別。例如人類、鳥類或者魚類等類別。這些類別不是實在的物體,只是人們抽象的描述與定義而已。
所以,物件導向程式設計當中也具有類別(Class),這些類別同樣抽象地描述了某些程式物件當中共同的屬性與方法。
- 類別的實例化:反過來說,因為,類別是抽象的描述與定義,所以,當類別被實例化(Instantiation)後,才是實在的物體。例如人類的實例化就是你、我與他。
同樣地,當程式開發者在物件導向程式中創造了一個類別後,它還不是一個實在的物件。它必須要透過實例化的指令來產生一個物件。
- 父類別與子類別:另外,類別是具有階層化的安排,就像人類下面可能還有白種人、黃種人或者黑種人,而不同人種之下可能還會區分成各自不同的族群。
在物件導向程式設計中,上層類別被稱為父類別(Super Class),而下層類別則稱為子類別(Sub Class)。
- 類別的繼承:因為,物件導向程式設計中的類別具有父類別與子類別之分,所以,自然會產生繼承的關係。
簡單地說,我們定義一個類別,它並不可能是無中生有,必然會延襲其它類別的一些屬性與方法。然後再從此基礎之上,繼續發展自己的屬性與方法。
這樣的機制便是繼承(Inheritance)。
本講義在此要特別強調的是,Java程式語言之中,即使某個子類別沒有指定它所繼承的父類別,JDK也會自動配置”java.lang.Object”類別做為它的父類別。
同時,Java程式語言並不能有多重繼承(Multiple Inheritance)的關係,亦即一個子類別只能繼承一個父類別,而不能繼承多個父類別。
Android程式設計:[class]宣告Android手機應用程式的主類別
經過上述初步的說明,您是否對物件導向程式設計的觀念有比較清晰的認知了呢?
所以,若我們將Android預設程式碼第四行:
public class Converter extends Activity{
}
描述成”宣告Converter子類別是繼承於Activity父類別”,您應該就不難理解了吧!(註:Java程式語言所使用的繼承語法為”extends”)
不過,您可能有個疑問:『”Activity”類別是打那兒來的呀?』
其實,就是在Android預設程式碼第二行”import android.app.Activity;”所連結存取而來的。
在此,還要補充一個重要觀念。在Android手機應用程式當中,每一個”Activity應用程式組件”型態的.java檔案可以定義許多的類別,但必然會有一個主類別。
而這個主類別名稱就是您當初在建立Android手機應用程式專案時,所指定的”Activity名稱”,同時,該程式的.java檔案名稱也是以此命名。比如,”Converter應用程式”的”Activity名稱”設定為”Converter”,所以主類別以及.java檔案便以此名稱命名。
以下則為第四行程式碼的補充說明。
- public修飾詞:首先,在Android預設程式碼第四行開頭所使用的”public”修飾詞(Modifier),是表示”Converter類別”是一個可供內外部套件類別存取的開放式類別。
- class類別關鍵詞:接續在”public”修飾詞後面的”class”類別關鍵詞,則表示此程式碼為物件類別(Class)的宣告,該關鍵詞後需接所要宣告的類別名稱。
- extends繼承關鍵詞:至於,在類別名稱之後的”extends”繼承關鍵詞則是Java程式語言的類別繼承語法,此關鍵詞後需接所要繼承的父類別。
- { }大括號:在Java程式語言當中,無論是類別或者是方法的宣告皆需在結尾加上{ },以便程式開發者在裡頭放置相關程式碼之內容。請注意,該大括號的後面無需再加上分號。
Android程式設計:建立文字註釋說明
Android預設程式碼的第五行:
/** Called when the activity is first created. */
該行程式碼並不會涉及程式的執行,它只是一個程式的文字註釋,藉以標註說明某段程式碼的意思。。(註:所有的註釋程式碼之結尾皆不需加上分號。)
除了”Annotation註釋”之外,Java程式語言在文字註釋的使用,大致可以使用以下三種方式:
- 單行文字註釋:格式為 // 文字註釋 ,使用於註釋只有單行文字的時候。
- 多行文字註釋:格式為 /* 文字註釋 */ ,使用於註釋有多行文字的時候。
- Java Doc文字註釋:格式為 /** 文字註釋 */ ,使用於註釋可被加註於Java Doc說明文件檔的時候。
由於,Android預設程式碼的第五行是採用”Java Doc文字註釋”的方式。因此,當採取此種註釋方式後,JDK會把這個註釋加註到”Converter應用程式”的Java Doc說明文件檔之中。
Android程式設計:建立應用程式的API說明文件
至於,什麼是Java Doc說明文件檔?
它是程式開發者利用JDK的”javadoc.exe”工具所建立的Java應用程式API說明文件網頁。這個說明文件網頁會以”doc”子目錄的方式,存在於應用程式專案目錄之下。
當然,Andorid手機應用程式也是Java應用程式之一,所以程式開發者亦可建立該說明文件。
在預設的狀態下,您的Andorid手機應用程式專案目錄之中並不存在此說明文件檔目錄,不過,您可以透過Eclipse來建立它。
至於,該怎麼做呢?
首先,請您選取Eclipse的”Project”下拉式功能表中的”Generate Javadoc”選項(如下圖箭頭1、箭頭2處所示)。
當出現”Generate Javadoc”對話視窗時,請您在”Javadoc command”欄位中輸入”javadoc.exe”檔案的所在路徑。(註:”javadoc.exe”檔案是存在於JDK目錄下的”bin”子目錄中。)
然後,請您按下”NEXT >”按鈕(如下圖箭頭1、箭頭2處所示)。
當出現下列對話視窗時,請您直接按下”Next>”按鈕(如下圖紅框處所示)。
接下來,為了讓說明文件網頁可以正常顯示中文內容,所以,必需設定該說明文件網頁的文字編碼為”UTF-8”。
因此,請您在下列對話視窗的”Extra Javadoc options”欄位之中,輸入”-charset UTF-8 –encoding UTF-8”,並按下”Finish”按鈕(如下圖箭頭1、箭頭2處所示)。
當出現”Update Javadoc Location”對話方塊時,請您按下”Yes To All”按鈕,以便產生或更新您的Java應用程式API說明文件網頁(如下圖紅框處所示)。
之後,您的Android手機應用程式專案目錄會新增一個名為”doc”的子目錄。
當您點選其中的”index.html”網頁檔案時,會出現您的Android手機應用程式API說明文件網頁之首頁(如下圖箭頭1處所示)。
另外,您會發現在”Method Summary”表格中,已出現Android預設程式碼第五行的”Called when the activity is first created.”註釋說明。
此代表該註釋已被正確加註於說明文件之中(如下圖箭頭2處所示)。
當然,您在Android手機應用程式開發的過程之中,皆可以運用上述的作法,隨時更新您的API說明文件網頁。
Anodrid程式設計:建立@Override的Annotation註釋
Android預設程式碼第六行:
@Override
該程式碼其實也是註釋的一種,Java程式語言稱這種形態為”Annotation註釋”。(註:此種註釋程式碼之結尾同樣無需加分號。)
不過,它主要的目的不是做為說明之用,而是當程式碼被編譯時,能提供Java程式語言編譯器(Compiler)注意。
”Annotation註釋”總共可分成三種,分別為”@Override”、”@Deprecated”、與”@SupressWarnings”。(資料來源:Java官網)
其中的”@Override”究竟是何意呢?
這必須談到類別繼承之下常會發生的覆寫動作(Overriding),以下為本講義對於覆寫的補充說明。
- 覆寫:由於,Android手機應用程式並沒有傳統Java應用程式慣用的main()方法之啟始點機制,而是,改採”Activity類別”中的Activity生命週期(Lifecycle)之相關方法來進行運作。(註:關於Activity生命週期之議題,本講義會在第八講當中詳述。)
其中,”onCreate(bundle)”方法負責Android手機應用程式首次被執行時,常態性的靜態初始化動作。
為了符合不同應用程式之需求,因此,這個靜態初始化動作還需要再加上應用程式本身所需的一些方法,它才能被運作。而非僅單純使用”onCreate(bundle)”方法。
所以,程式開發者需要重新宣告一個新的”onCreate(bundle)”同名方法,然後再重新呼叫”Activity類別”原有的”onCreate(bundle)”方法,以便與自己所需的相關方法相結合。
這種子類別重新宣告父類別同名方法的動作,便稱為覆寫(Overriding)。
所以,在Android預設程式碼的第六行設置”@Override“之Annotation註釋的主因,就是為了當程式碼被編譯成.class類別檔案時,告知Java程式語言編譯器(Compiler)說:『下面宣告的方法有覆寫動作,假若該方法並未與其父類別當中的方法同名,則需以錯誤訊息的方式提醒程式開發者。』
不過,目前的Android開發環境其實提供了很不錯的除錯機制,因此,當程式碼還未被編譯之前,就能找出上述的錯誤。
例如,我們將”onCreate(bundle)”方法的名稱改為”test(bundle)”方法。由於它的上面已有加註”@Override”之Annotation註釋,因此,在該行程式碼的前面會馬上顯示錯誤符號。
當您將滑鼠游標指向該錯誤符號時,則會顯示”The method test(Bundle) of type Converter must override a superclass method”錯誤訊息。簡而言之,該方法必需要覆寫一個父類別的同名方法,而”test(Bundle)”並非Activity類別的同名方法。
由上亦可知,”@Override” 之Annotation註釋除了跟其它文字註釋一樣,不會涉及程式的執行外。它更可以避免程式開發者在覆寫動作上的程式撰寫錯誤。
Android程式設計:覆寫Activity類別的onCreate(bundle)方法
由上可知,Android預設程式碼在第六行加上”@Override”之Annotation註譯,主要就是為了配合第七行自行宣告的”onCreate(bundle)”方法。
Android預設程式碼第七行為:
public void onCreate(Bundle savedInstanceState) {
}
由於,我們剛才已將”onCreate(bundle)”進行了初步的介紹,因此,在此不再重述”onCreate(bundle)”方法的細節。以下為該行程式碼的其它補充說明:
- public修飾詞:在”onCreate(bundle)”方法開頭的”public”修飾詞(Modifier),它是用來設定該方法為可供內外部套件類別存取的開放式方法。
- void傳回值型態:其次,”public”修飾詞後面的”void”傳回值型態(Return type)則是宣告該方法無傳回值。
亦即,”onCreate(bundle)”方法執行完畢後,不會產生任何可回傳(return)的數值。
- bundle集合型別之savedInstanceState參數:”onCreate(bundle)”方法的括號裡頭有一個被宣告為”bundle”集合型別的”savedInstanceState”參數(Parameter)。
為何會有這個名稱為”savedInstanceState”的參數呢?
簡單地說,手機應用程式所處的環境與個人電腦環境不同。比如,當某個手機應用程式正在手機用戶執行時,突然有通電話打進來,則該應用程式就會被突然停止(Stop)。
另外,當手機的主記憶用量不足時,作業系統為求重要的通訊功能可以正常運作,因此,有些比較不重要的手機應用程式也有可能被突然停止。
為求這種被突然停止的手機應用程式,可以在重新被執行時,恢復停止當時的使用者介面之狀態資訊(The state of the user interface)。
因此,Android會在該應用程式被停止時,透過”onSaveInstanceState(bundle)”方法儲存應用程式的使用者介面之狀態資訊。
當這個應用程式再度透過”onCreate(bundle)”方法進行靜態初始化動作時,會將”savedInstanceState”參數同時載入,以便恢復應用程式停止前的使用者介面之狀態。
反之,假若該應用程式執行時為全新的狀態,則”savedInstanceState”參數為空值(null),並不具任何效用。
至於,”bundle”集合型別又是什麼呢?
Android Developers官網將其描述為:『A mapping from String values to various Parcelable types.』
簡單地說,”bundle”集合型別類似Java的”HashMap”集合型別,它是一個具有索引鍵(Key)與索引值(Value)的物件集合,”onCreate(bundle)”方法利用它來存放使用者介面的狀態資訊。(註:此部份涉及Activity生命週期,我們在第八講義會再做更深入的探討。)
因為,”bundle”集合型別是Android所自行定義,所以Android預設程式碼的第三行,才會連結存取”android.os.Bundle”套件類別,以供”onCreate(bundle)”方法定義型別使用。
Android程式設計:重新呼叫Activity類別的onCreate(bundle)方法
本講義在剛才有談到:
『”onCreate(bundle)”方法負責Android手機應用程式首次被執行時,常態性的靜態初始化動作。
為了符合不同應用程式之需求,因此,這個靜態初始化動作還需要再加上應用程式本身所需的一些方法,它才能被運作。而非僅單純使用”onCreate(bundle)”方法。
所以,程式開發者需要重新宣告一個新的”onCreate(bundle)”同名方法,然後再重新呼叫”Activity類別”原有的”onCreate(bundle)”方法,以便與自己所需的相關方法相結合。』
所以,當Android預設程式碼在第七行覆寫了一個與Activity類別同名的”onCreate(bundle)”方法後,還需要在第八行重新呼叫”Activity類別”原有的”onCreate(bundle)”方法,藉以喚回”Activity類別”原有的”onCreate(bundle)”方法,並由此開展自己的程序。
所以,Android預設程式碼第八行為:
super.onCreate(savedInstanceState);
以下則為該行程式碼的補充說明:
- super關鍵詞:由於,Android預設程式碼早已宣告了新的”onCreate(bundle)”方法,因此,在”Converter應用程式”當中的”onCreate(bundle)”方法已並非是”Activity類別”原有的”onCreate(bundle)”方法,亦即它已行使覆寫的動作。
如果要在新的”onCreate(bundle)”方法中,喚回”Activity類別”原有的”onCreate(bundle)”方法,還需要使用”super”關鍵詞來指定呼叫父類別中的方法。
Java程式語言當中的”super”關鍵詞,是做為子類別指定呼叫父類別的屬性或方法之用。當然,父類別在此指的是”Activity類別”。
另外,在Java程式語言的語法方面,”super”關鍵詞與父類別的屬性或方法之間,需以 . 做為間隔。
- onCreate(bundle)方法:至於,該行程式碼之中的”onCreate(bundle)”方法則是源於”Converter類別”所繼承的”Activity類別”之方法。
在此要特別注意的是,假若,”super”關鍵詞後面所接的屬性或方法並非”Activity類別”所有,則會造成程式碼在編譯時的錯誤。
不過,目前的Android開發環境提供了很不錯的除錯機制,因此,當程式碼還未被編譯之前,其實就能找出上述的錯誤。
例如,我們若將”onCreate(bundle)”方法的名稱改為”test()”方法。由於,”Converter類別”所繼承的”Activity類別”之下並沒有”test()”方法,因此,在該行程式碼的前面會馬上顯示錯誤符號。
當您將滑鼠游標指向該錯誤符號時,則會顯示”The method test() is undefined for the type Activity”錯誤訊息。簡而言之,該訊息提醒您:因為”Activity類別”並沒有定義過”test()”方法。所以,需要更正成”Activity類別”當中所具有的方法。
- savedInstanceState參數:在Android預設程式碼第七行所自行宣告的”onCreate(bundle)”同名方法之中,早已定義了一個”bundle”集合型別的”savedInstanceState”傳入參數。
這個傳入參數必需要傳入原有的”Activity類別”之”onCreate(bundle)”方法中,才能發揮其作用。
因此,在喚回”Activity類別”原有的”onCreate(bundle)”方法的同時,程式碼必須一併將這個”savedInstanceState”參數傳入。
當然,”savedInstanceState”傳入參數的初始值為空值(null)。
它必須在遇到應用程式停止(Stop)時,Android才會將停止當時的使用者介面之狀態資訊(The state of the user interface)透過”onSaveInstanceState(bundle)”方法存入”savedInstanceState”傳入參數當中。
至於,為何它不像第七行自行宣告”onCreate(bundle)”同名方法一樣,在參數名稱前面加上”bundle”集合型別定義呢?
因為,它只是呼叫”Activtiy類別”所即有的”onCreate(bundle)”方法,而非宣告一個新方法。所以,只要把同為”bundle集合型別”的參數傳入該方法即可,不需要再進行型別的定義。
Android程式設計:呼叫Activity類別的setContentView(int)方法
第九行是整個Android預設程式碼當中,唯一真正在手機螢幕上執行的動作。
Android預設程式碼第九行為:
setContentView(R.layout.main);
以下則為該行程式碼的補充說明:
- setContentView(int)方法:在該行當中的”setContentView(int)”方法跟”onCreate(Bundle)”方法同樣也是源自於”Activity類別”。
寫到此,您可能會問:『為何它沒有在方法名稱的前面加上”super”關鍵詞?』
因為,此方法並沒有涉及到覆寫的問題,因此,它的程式碼可以用呼叫方法的正常規則來撰寫,不需要再加上”super”關鍵詞。
至於,”setContentView(int)”方法的作用是什麼呢?談此之前,我們必需先深入探究第六講所談及旳內容。
我們在第六講之中有提到,介面設計構成主要分成兩大部份:
『其一為介面排版元件(Layouts)、其二則為介面功能元件(View,又稱Widget)。』
所以,您在Android介面設計的時候,會先將介面排版元件(Layouts)拖曳至介面編輯區中,然後再依序將一些介面功能元件(View,又稱Widget),如按鈕(Button)、文字欄位框(EditText)、文字標籤(TextView)等拖曳至介面排版元件(Layouts)裡頭。
深入來說,整個Android介面設計的組成結構,就如同階層化的樹狀(Tree)資料結構一般,從最頂端的介面排版元件至底端的介面功能元件。
其中,介面排版元件是作為介面功能元件的容器結構,它可以容納不同的介面功能元件。
介面排版元件也可以像俄羅斯套娃一樣,往下再容納其它的介面排版元件。
Android將此結構抽象化描述成為介面元件階層圖(View Hierarchy)。
介面元件階層圖(View Hierarchy)包括了指涉於介面排版元件(Layouts)的”ViewGroup”,以及指涉於介面功能元件(View,又稱Widget)的”View”,本講義以”Converter應用程式”的介面設計為例,繪製如下之介面元件階層圖。
其中,”ViewGroup”其實是Android介面結構之中相當巧妙的安排。因為,它將原本水平化的介面元件關係,透過”ViewGroup”來進行”View”的群集與堆疊。進而形成具上下階層關係的介面結構。
每一個應用程式的介面不再只是鬆散的介面元件配置,而它必然有一個最頂層”ViewGroup”的根節點(Root Node),從它之下再開展出不同的介面階層關係。
另外,該階層圖中的父節點(Parent Node)必然是”ViewGroup”,而子節點(Child Node)則可以是”View”或”ViewGroup”。
就物件導向程式設計的觀點來說,介面排版元件(Layouts)指的是繼承於”ViewGroup類別”之下的各種子類別物件,它為Android介面提供了多樣化的排版(Layout)物件。
介面功能元件(View,又稱Widget)則指的是繼承於”View類別”之下的各種子類別物件,它為Android介面提供多樣化的使用者介面(User Interface, UI) 物件。
講到此,您或許會問:『為何本講義一下子將”View”翻譯成介面元件、一下子又翻譯成介面功能元件?』
這是因為”View”是Android介面的最基礎單元,除了專指介面功能元件(View,又稱Widget)外,又因Android介面上的全部物件皆繼承於”View類別”,包括”ViewGroup類別”也是源於”View類別”。所以,它也是所有介面元件的源頭與總稱。
回過頭來說,本講義之所以會透過上述較長之篇幅,去深入討論介面元件階層圖(View Hierarchy)的內容,是因為它與”setContentView(int)”方法"之運作有很大的關係。
由於,Android系統是以介面元件階層圖的方式來進行螢幕畫面的繪製工作。因此,當”setContentView(int)”方法被執行時,應用程式會先傳遞一個參照(reference)給根節點((Root Node)物件。
在Android系統接收到此參照之後,為了要繪製這個新的介面,所以,它會利用這個參照使目前即有的介面元件階層圖整個失效(invalidate),並重新測量(measure)與繪製(draw)新的介面元件階層圖。
此外,階層圖中的父節點會決定子節點在它的容納空間之中的位置(Location)與尺寸(Size)。
當決定好之後,子節點會自行繪製它自己的介面元件。依此類推,逐漸展開該介面之全局。(資料來源:Android Developers 官網)
另一方面,初接觸Android手機應用程式的朋友,可能會覺得Android採取XML檔案的介面設計方式與HTML檔案的網頁設計方式很像。
的確,它們兩者同樣是以標記語言(Markup Language)的模式進行介面的配置描述。
不過,它們兩者的不同在於HTML的標記是由W3C組織所定義與維護,只要有支援HTML直譯的網頁瀏覽器便能解讀顯示HTML標記所描述的畫面。
而Android的XML標記,則是Android自行定義與維護,並且,它只能在具有Android作業系統的硬體上顯示它所描述的畫面。
另外,HTML檔案並沒有被預先編譯,而是直接在瀏覽器當中直譯顯示。
但是,Android的XML介面檔案則會預先被編譯成二進位格式後,才會被解讀並顯示在手機螢幕上。
- R.layout.main參數:在”setContentView(int)”方法裡頭有一個”int”整數型別的傳入參數”R.layout.main”。如果您有熟讀本講義第五講與第六講的話,應該會直覺地想到此傳入參數必然與”r.java”檔案有關係。
沒錯!它正是指涉於”r.java”檔案當中的屬性值。
更進一步地說,”r.java”檔案包含了一個名為”R”的類別,在它之下有”attr”、”drawable”、”id”、”layout”與”string”等子類別。
這些子類別當中定義了許多的屬性。這些屬性正好對應到”res”目錄下的各類資源檔案或者這些檔案中的變數。
不知您是否還記得?我們曾在第五講當中提過:「每當開發者在”res”目錄增加一個資源檔案時,在”r.java”檔案當中就會相對地自動配置一個索引代號給它,以便開發者得以在應用程式當中做呼叫的動作。」
其實,第五講裡頭所講的”自動配置一個索引代號”之意,其實是指在該資源檔案或變數所對應的”R類別”之子類別中,自動新增一個屬性,並將索引代碼數值配置給該屬性。
例如,我們在第六講中所設計的”main.xml”介面檔案,它便被自動在”R類別”中的”layout子類別”,新增一個名為”main”的類別屬性,並給予一個索引代號(如下圖箭頭指引處所示)。
由於,此屬性的型別已被定義成”int”整數型別,因此,”setContentView(int)”的這個傳入參數同為”int”整數型別。
說到這兒,您可能會有個疑問:「Android為何不要讓應用程式能夠直接存取”res”目錄下的檔案,還要特別設置一個”R類別”來間接索引呢?」
這是因為”res”目錄下的各類資源檔案,在Android手機應用程式的產生過程中會被預先編譯成二進位的資源格式,而非以原始檔案形式存在。因此,需要透過”R類別”的方式來進行資源格式的索引動作。(資料來源:Android Developers官網)
此法的優勢在於這些檔案已被編譯成二進位的資源格式,因此,相較於直接存取原始檔案來說,它會減少許多手機運算上的負擔。
上述,本講義已把十一行Android預設的程式碼解說完畢。
您可以先執行看看此Android預設程式碼。
請您按下Eclipse工具列當中的”Run”按鈕。
當Converter應用程式成功在Android模擬器當中執行時,會出現下列的畫面。
請注意,它真的就只是畫面而已!
當您在”kg”文字輸入框中輸入任何數字,並按下”Convert”按鈕時,它並不會為您進行任何換算的動作。
因為,Android預設程式碼就只是負責把您設計好的介面顯示出來,而不包含數值換算的運算動作。所以,我們必須以此預設程式碼為基礎,自行加上”公斤數”換算”磅數”的程式碼,以完成這個應用程式的初步目的。
本講義將於第七講的下篇,帶領您一步一步完成此應用程式的程式撰寫工作。
此篇講義的主要參考文獻來源:Android Developers 官網、Java 官網
第七講上篇完畢!歡迎繼續閱讀第七講下篇”Android 手機程式開發教學課程《免費講義 7-2》:Android 程式設計教學 - 給Java初學者的第一個Android程式範例 [下篇] ”。
如果您對於Andorid手機應用程式開發有興趣,歡迎閱讀我們在網路上發表的Android手機應用程式開發教學系列講義。
本講義目前網路連載發表有:Android手機程式開發教學講義懶人包、Android 教學講義第一講、Android 教學講義第二講、Android 教學講義第三講、Android 教學講義第四講、Android 教學講義第五講、Android 教學講義第六講、Android 教學講義第七講上篇、Android 教學講義第七講下篇、Android 2.3補充教材1、Android 2.3補充教材2、Android 3.0平板電腦完整功能搶先看(From T-Mobile)、Android 3.0 平板電腦應用程式開發:第一講、Android 3.0 SDK 正式版登場、Android 嵌入式系統最新開發應用 - SAAB IQon 車用電腦、Android 2.3 補充教材3、Android 3.0 平板電腦應用程式開發:第二講、Android 教學講義第八講上篇、Android 教學講義第八講中篇(1)、Android 4.0 SDK 開發功能介紹與下載網址、 Android 4.0 SDK 下載安裝完整教學、 Android 4.0 模擬器安裝設定教學課程講義、Android 4.0 的 Holo theme 佈景主題介紹與設定教學課程講義、Android 4.2 升級功能簡介、Android 4.2 SDK & ADT Bundle 下載安裝教學、2013年第1講: Android Application Project 之建立、2013年最新 Android Studio 開發工具下載安裝教學、最新 Android App 網路連線程式設計範例 (第一講) - Volley HTTP Library 入門教學、Android App 與 Android Application Project 是什麼?、Android 4.4 KitKat 與 Android 4.4 SDK 開發功能介紹、Android SDK 下載安裝中文教學課程講義 ( 2013年11月新版,ADT Bundle )
喜歡閱讀我們的講義嗎?歡迎加入我們所成立的《Android 手機程式開發教學課程免費講義》網路讀者俱樂部會員(請點選此連結),謝謝!
著作權聲明
Android 程式設計教學 - 給Java初學者的第一個Android程式範例 [上篇] - Android 手機程式開發教學課程免費講義 7-1 第一版本完成日:2010年10月30日
本講義之內文、排版等著作權或其他智慧財產權歸屬 孫傳雄 與 孫傳雄研究室 所有,非經書面同意禁止任何形式之翻印、全文轉貼或者授課使用行為。但例外允許在網際網路上引用此講義之網址連結。
本講義之內文所提及或者引用的公司名稱、產品名稱以及所引用的文字、商標、Youtube短片、產品相片或者網站頁面,均為其所屬公司所擁有,特以聲明。