1. 事前準備
本程式碼研究室將說明如何自行建構一款名為「Lemonade」的新應用程式,並引導您逐步完成專案,包括在 Android Studio 中進行設定和測試。
本程式碼研究室與本課程中的其他部分不同。與先前的程式碼研究室不同,本程式碼研究室的目的並不是逐步說明如何建構應用程式,而是設定將由您獨力完成的專案,提供自行完成應用程式及檢查工作成果的相關指示。
我們改為一併在您將下載的應用程式中提供測試套件,而非程式碼解答。您將在 Android Studio 中執行這些測試 (本程式碼研究室稍後會說明操作方法),並查看程式碼是否通過測試。這可能需要多試幾次,即使是專業開發人員也很難第一次嘗試就通過所有測試!程式碼通過所有測試後,您就能將這項專案視為完成。
我們瞭解,您可能只是想獲得解答來對照檢查。我們特意不提供程式碼解答,是因為希望您能透過練習,體驗專業開發人員的作業環境。您可能會需要用到較不嫻熟的其他技能,例如:
- 在 Google 上搜尋您在應用程式中不認得的字詞、錯誤訊息和程式碼片段。
- 測試程式碼、解讀錯誤,然後變更程式碼並重複測試。
- 回去閱讀先前在 Android 基本概念單元 1 中的內容,溫故知新。
- 將您知道可順利執行的程式碼 (也就是專案內提供的程式碼,或是您先前在單元 1 中學到的其他應用程式的程式碼解答) 與您編寫的程式碼進行比對。
乍看之下可能很困難,但我們百分之百相信如果您能夠完成單元 1,您就已經準備好進行這項專案。請按照自己的步調進行,不要放棄,我們對您有信心。
必要條件
- 此專案適用於已完成「Android Kotlin 基本概念」課程單元 1 的使用者。
建構項目
- 您將使用單元 1 中學到的技能,建構簡單的 Lemonade 應用程式。
軟硬體需求
- 已安裝 Android Studio 的電腦。
2. 應用程式總覽
歡迎參與「專案:Lemonade 應用程式」!
我們已將您召集至團隊中,協助我們實現製作數位檸檬水的願景。我們目標是建立簡單的互動式行動應用程式,讓您可以使用該應用程式榨取一杯檸檬汁。您可以將此視為一種概念的呈現,或是當做趣味消遣活動!
成品 Lemonade 應用程式將由單一畫面組成。使用者初次啟動應用程式時,系統會提示使用者輕觸檸檬樹的圖片,藉此挑選檸檬。
使用者在輕觸檸檬樹後便會看到一顆檸檬,可以輕觸以「擠壓」檸檬數次 (次數不固定,系統將隨機產生所需的擠壓次數),才會移動到下一個畫面。
使用者輕觸擠壓至正確次數後,便會看到玻璃杯圖片,可以「喝下」檸檬水。
按一下飲用檸檬水之後,玻璃杯就會變成空的,使用者只要再次輕觸圖片,就能返回第一個畫面,再從檸檬樹中選取其他檸檬。
這款應用程式的設計簡單,且提供單一活動。應用程式的不同狀態 (使用者選取檸檬、擠壓檸檬、喝檸檬水、以及最後的空杯) 都會以「狀態機器」呈現。雖然這聽起來像是空泛的理論術語,但這僅表示應用程式的狀態 (也就是要向使用者顯示哪些文字和圖片) 是取決於包含應用程式狀態的變數 (select
和 squeeze
等等)。系統會一併更新應用程式的狀態會連同任何其他必要的變數,並在完成所有更新後分別設定使用者介面 (設定圖片和文字)。
系統已定義應用程式狀態的所有變數。您的工作是建構應用程式的版面配置並實作邏輯,讓使用者介面按預期在每個狀態之間轉換。
測試程式碼
對於 Lemonade 應用程式 (以及日後的專案),系統會提供一些自動化測試,讓您驗證程式碼的運作狀況是否符合預期。
確切來說,自動測試是什麼?在軟體開發中,您可以將「測試」視為程式碼,驗證其他程式碼是否可正常運作。方法是檢查輸出 (例如畫面上使用者介面元素的內容),看看輸入的結果是否合理 (稱為「測試案例」)。Lemonade 應用程式的範例專案包含幾項測試,您可以執行測試,確認邏輯是否已正確實作。本文稍後會詳細說明測試。您現在可以下載範例程式碼,並開始建構 Lemonade 應用程式了。
3. 開始操作
下載專案程式碼
請注意,資料夾名稱是 android-basics-kotlin-lemonade-app
。在 Android Studio 中開啟專案時,請選取這個資料夾。
如要取得這個程式碼研究室的程式碼,並在 Android Studio 中開啟,請按照下列步驟操作:
取得程式碼
- 按一下上面顯示的網址。系統會在瀏覽器中開啟專案的 GitHub 頁面。
- 檢查並確認分支版本名稱與程式碼研究室中指定的版本相符。例如,在下列螢幕截圖中,分支版本名稱為「main」。
- 在專案的 GitHub 頁面中,按一下「Code」按鈕,畫面上會出現彈出式視窗。
- 在彈出式視窗中,按一下「Download ZIP」按鈕,將專案儲存至電腦。等待下載作業完成。
- 在電腦中找到該檔案 (可能位於「下載」資料夾中)。
- 按兩下解壓縮 ZIP 檔案。這項操作會建立含有專案檔案的新資料夾。
在 Android Studio 中開啟專案
- 啟動 Android Studio。
- 在「Welcome to Android Studio」視窗中,按一下「Open」。
注意:如果 Android Studio 已開啟,請改為依序選取「File」>「Open」選單選項。
- 在檔案瀏覽器中,前往已解壓縮的專案資料夾所在的位置 (可能位於「Downloads」資料夾中)。
- 按兩下該專案資料夾。
- 等待 Android Studio 開啟專案。
- 按一下「Run」按鈕 即可建構並執行應用程式,請確認應用程式的建構符合預期。
請花點時間熟悉範例專案。請特別留意 MainActivity.kt
檔案。
在 MainActivity.kt
中,您會看到多個變數,用來呈現應用程式目前的狀態。在接下來的步驟中,您會使用這些變數讓應用程式與使用者互動。雖然這裡的程式碼數量可能會讓人感到頭昏腦脹,但您不需要修改任何未標示 TODO 的程式碼。我們會在以下頁面中提供特定指示。
您也會發現,專案中包含另一個套件 com.example.lemonade (androidTest)。
這包含了一些自動化測試,用來驗證 MainActivity.kt
中實作的功能是否正確。稍後會再詳細說明。您現在可以開始透過使用者介面建構應用程式。
4. 建立使用者介面
Lemonade 應用程式只需要基本的版面配置;您只需要兩個檢視畫面,就能實作所有功能。
- 未使用者提供操作說明的
TextView
。 - 根據應用程式目前狀態 (例如要擠壓的檸檬) 顯示圖形的
ImageView
。
您會在 activity_main.xml
中建立這個版面配置。
您的目標是運用您掌握的版面配置編輯器知識,建構如下版面配置:兩個檢視畫面都在畫面中央,且 TextView
位於 ImageView
上方。
5. 讓應用程式與使用者互動
版面配置完成之後,請開啟 MainActivity.kt
。您可以在這裡實作所有應用程式的邏輯。您會發現已經有一些程式碼。且有許多標示為 // TODO:
的註解 (如以下範例所示)。這些都是您要完成的工作。
您必須實作下列三項基本工作,才能讓 Lemonade 應用程式正常運作。
- 設定
lemonImage
ImageView
以回應使用者輸入的內容。 - 實作
clickLemonImage()
以更新應用程式的狀態。 - 實作
setViewElements()
,以根據應用程式目前的狀態更新使用者介面。
逐一檢查各項工作。
步驟 1:設定 ImageView
輕觸圖片檢視畫面後,應用程式就會從一個狀態切換成其他狀態。在 onCreate()
結尾,需要設定兩個事件監聽器。
setOnClickListener()
應更新應用程式的狀態。方法是clickLemonImage()
。setOnLongClickListener()
會回應使用者長按圖片的事件 (例如,使用者輕觸圖片,而且沒有立即放開手指)。對於長按事件,畫面底部會顯示小工具 (稱為 Snackbar),讓使用者知道他們擠壓檸檬的次數。這是透過showSnackbar()
方法來完成。
在下一個步驟中,您將實作變更應用程式狀態的邏輯。
步驟 2:實作 clickLemonImage()
完成前一個步驟後,每當使用者輕觸圖片時,系統就會呼叫 clickLemonImage()
方法。這個方法負責將應用程式從目前狀態移至下一個狀態,並視需要更新變數。有四種可能的狀態:SELECT
、SQUEEZE
、DRINK
和 RESTART
;目前狀態會以 lemonadeState
變數呈現。這個方法需要針對每個狀態完成不同動作。
SELECT
:轉換為SQUEEZE
狀態,透過呼叫pick()
方法並將squeezeCount
(使用者擠壓檸檬的次數) 設為 0 來設定lemonSize
(需要擠壓的次數)。SQUEEZE
:將squeezeCount
增加 1,並將lemonSize
減少 1。別忘了檸檬需要不同次數的擠壓,應用程式才會轉換其狀態。只有在新的lemonSize
等於 0 時,才轉換至DRINK
狀態。否則應用程式應保持在SQUEEZE
狀態。DRINK
:轉換為RESTART
狀態,並將lemonSize
設為 -1。RESTART
:切換回SELECT
狀態。
處理完所有更新和狀態轉換後,請務必呼叫 setViewElements()
,根據新狀態更新使用者介面。
步驟 3:實作 setViewElements()
setViewElements()
方法負責根據應用程式的狀態更新使用者介面。文字和圖片應更新為下方顯示的值,以符合 lemonadeState
。
SELECT
:
- 文字:按一下即可選取檸檬!
- 圖片:
R.drawable.lemon_tree
SQUEEZE
:
- 文字:按一下即可擠檸檬汁
- 圖片:
R.drawable.lemon_squeeze
DRINK
:
- 文字:按一下即可喝檸檬水!
- 圖片:
R.drawable.lemon_drink
RESTART
:
- 文字:按一下即可重新開始!
- 圖片:
R.drawable.lemon_restart
如何使用字串資源
在 Android 中,幾乎所有內容都是資源。定義您可以在應用程式中存取的資源,是 Android 開發作業中不可或缺的一環。
資源可用於定義顏色、圖片、版面配置、選單和字串值。這種做法的好處是沒有硬式編碼。這些資源檔案中定義了所有內容,您可以在應用程式的程式碼中參照。這些資源最簡單 (且最常見) 的使用方式是使用字串資源,允許具有彈性的本地化文字。
字串或靜態文字可儲存在稱為 strings.xml 的個別檔案中,strings.xml 位於 res 資料夾的值子資料夾內。
針對您想要在應用程式中顯示的每段文字 (即按鈕標籤或 TextView
內的文字),您必須先定義 res/values/strings.xml
檔案中的文字。每個項目都是索引鍵 (代表文字 ID) 和值 (文字本身)。舉例來說,如果您想讓按鈕顯示「Submit」(提交),請在 res/values/strings.xml
中加入以下字串資源:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello!</string>
<string name="submit_label">Submit</string>
</resources>
如要直接存取程式碼中的資源,只要使用 getResources.getString()
或 getString()
方法,即可依照資源 ID R.string.submit_label
來存取相應的值。
val submitText = getResources().getString(R.string.submit_label)
如要直接將字串資源中的文字設定為 TextView,您可以呼叫 TextView 物件上的 setText()
,並傳入資源 ID。
val infoTextView: TextView = findViewById(R.id.info_textview)
infoTextView.setText(R.string.info_text)
字串資源也可以包含特殊字元,以便設定文字格式。舉例來說,可能會有字串資源可讓您將其他文字插入字串。
<string name="ingredient_tablespoon">%1$d tbsp of %2$s</string>
在程式碼中,您可以透過傳遞引數來存取字串資源,並設定字串資源的格式。
getResources().getString(R.string.ingredient_tablespoon, 2, "cocoa powder")
宣告字串資源時,每個引數都會依照顯示的順序編號 (1
、2
等),並以字母表示不同類型 (d
代表小數,s
代表字串等等)。正確類型的引數可傳遞至 getString()
的呼叫。
2 tbsp of cocoa powder
詳情請參閱字串資源說明文件。
6. 執行應用程式
建立應用程式的使用者介面並實作主要活動後,就可以查看實際的工作成果。使用「Run」>「Run ‘app'」選單來執行應用程式,模擬器隨即啟動。
應用程式現在應該具備完整的互動功能,您應該可以輕觸圖片檢視畫面來切換狀態。
當螢幕上顯示檸檬時,您也可以長按 (按住) ImageView
,以查看畫面底部的 Snackbar,上面會顯示已擠壓檸檬幾次。請花一點時間執行應用程式幾次,執行過所有的狀態。然後休息一下,辛苦了!
7. 測試操作說明
測試應用程式
您已完成 Lemonade 應用程式的實作,但在專業軟體開發作業中,撰寫程式碼之後通常還有其他步驟。除了應用程式的程式碼以外,專業品質的應用程式還包括測試程式碼,可確認程式碼是否能正常運作,並確保程式碼的變更不會造成新的錯誤,這個過程稱為自動化測試。雖然自動化測試教學不在這個專案的涵蓋範圍內,但 Lemonade 應用程式會隨附一些測試,協助您確認是否已正確實作專案。您可以藉此進行自我評分,查看是否已達到所有專案要求,以及應用程式是否需要進行任何變更。
「測試」是什麼?測試指的是 Android Studio 專案中的程式碼片段,這些程式碼片段會執行應用程式的部分程式碼,根據應用程式的程式碼是否正常運作,測試會得到「通過」或「失敗」的結果。
該如何尋找並執行應用程式的測試?您可以在測試「target」中找到 Lemonade 應用程式的測試。「目標」是軟體開發詞彙,適用於結合再一起的類別組合。舉例來說,Lemonade 應用程式存在於名為「應用程式」的目標中,而測試則位於「LemonadeTests」目標中。雖然 LemonadeTests 目標可以從應用程式目標存取程式碼,但兩者是完全獨立的,應用程式的程式碼不含任何測試程式碼。
在「Android」檢視畫面中查看檔案時,測試目標會顯示應用程式的套件名稱,但會包含 (androidTest)。
參照測試程式碼時也有一些需要知道的重要詞彙。
- 測試套件 - 包含所有「測試案例」的目標。
- 測試案例 - 這個類別包含相關功能的個別測試 (Lemonade 應用程式只有一個測試案例,但更大型的應用程式通常會有更多測試案例)。
- 測試 - 用來測試特定項目的函式。
測試案例可以有多個測試,且專案的測試套件可以有多個測試案例。
執行測試
如要執行測試,請執行下列其中一項操作:
若是單一測試案例,請開啟測試案例類別,然後按一下類別宣告左側的綠色箭頭。接著從選單中選取「Run」選項。這麼做將會執行測試案例中的所有測試。
您通常只需要執行一項測試,例如只有一個測試失敗,另一個則通過測試。執行單一測試的做法,與執行整個測試案例一樣。使用綠色箭頭並選取「Run」選項。
如果您有多個測試案例,也可以執行整個測試套件。就像執行應用程式一樣,您可以在「Run」選單中找到這個選項。
請注意,Android Studio 會預設為您所執行的最後一個目標 (應用程式、測試目標等),因此如果選單仍顯示「Run」>「Run ‘app'」,您可以依序選取「Run」>「Run」以執行測試目標。
然後從彈出式選單中選擇測試目標。
測試執行結果會顯示在「Run」分頁標籤中。左側窗格中會顯示失敗測試清單 (如果有的話)。如果測試失敗,函式名稱旁邊會標上紅色驚嘆號;通過的測試會以綠色勾號標示。
如果測試失敗,文字輸出會提供相關資訊,協助您修正導致測試失敗的問題。
例如,在上述錯誤訊息中,測試會檢查 TextView
是否使用了特定字串資源。然而,測試失敗了。「Expected」和「Got」之後的文字不相符,代表測試預期的值與執行中應用程式的值不相符。在這個例子中,TextView
中使用的字串並非是預期的實際 squeeze_count
。
8. 選擇性:分享應用程式!
當品嚐許多杯檸檬水後,您可以將喜愛的畫面擷取下來,並且在 Twitter 上分享,展示您的學習成果。標記 @AndroidDev 並新增主題標記 #AndroidBasics。