瞭解如何在 debugging 時使用中斷點(breakpoints),並留意特定變數。
到目前為止,大多數的新手 developers 可能已經會使用 Log statements 進行 debugging。完成單元 1 後,您將學到如何解讀 stack traces 和研究 error messages。雖然這兩種工具都是功能強大的 debugging 工具,但現代 IDE 提供更多功能,讓您的 debugging 流程更有效率。
在本課程中,您將瞭解 Android Studio 整合的 debugger、如何暫停執行 app,以及一次執行單行程式碼,找出 bug 的確切來源。此外,您將學會如何使用一項稱為 Watches 的功能以及如何追蹤特定變數,而不必新增特定的 log statements。
學習目標
- 如何將 debugger 附加到運作中的 app。
- 使用中斷點(breakpoints)來暫停執行中的 app,逐行檢查程式碼。
- 將條件運算式加入中斷點(breakpoints)以節省 debugging 時間。
- 在 Watches 窗格中新增變數,以輔助 debugging。
建立新 project
我們不會一開始就對複雜的大型 app 進行偵錯,而是會從空白專案著手並介紹一些錯誤程式碼,藉此展示 Android Studio 中的偵錯工具。
建立新的 Android Studio 專案,即可開始使用。
在「Select a Project Template」(選取專案範本) 畫面中選擇「Empty Views Activity」(空白活動)。
將應用程式命名為「Debugging」,接著確認語言已設為 Kotlin,其他項目則保持不變。
系統將開啟一項新的 Android Studio 專案,並顯示一個名為
MainActivity.kt
的檔案。
回報 bug
還記得單元 1 中 debugging 課程的除以零範例嗎?在迴圈(loop)的最終迭代(iteration)中,app 嘗試執行除以零時,因為不可能除以零,因此 app 當機,並彈出 java.langArithmeticException
。藉由檢查 stack trace 找出 bug 並予以解決,並且使用 log statements 驗證該假設。
由於您已經熟悉那個範例,因此將用於示範中斷點(breakpoints)的使用方式。breakpoints 會逐行處理程式碼,不必先新增 log statements 或重新執行 app。
- 開啟
MainActivity.kt
,並將程式碼替換為以下程式碼:
1 | package com.example.myapplication |
- 執行 app。觀察 app 是否如預期當機。

使用 breakpoints debug
瞭解 logging 後,您已學會如何有策略地放置 logs,以便識別錯誤及驗證問題是否已修正。然而,在面對並非您導入的 bugs 時,我們未必能明確得知要將 log statements 放置在何處,或是要輸出哪些變數。通常,您只能在執行階段(runtime)找到這項資訊。
1 | fun division() { |
此時,中斷點(breakpoints)就能發揮功效。即使您已根據堆疊追蹤(stack trace)中的資訊大致推斷出造成 bug 的原因,您仍可在某行程式碼新增 breakpoints 做為停止訊號。一旦觸及 breakpoints,系統就會暫停執行程式碼,讓您可以在執行階段使用其他 debugging 工具,以便詳細瞭解實際情況並判斷問題。
附加 debugger
Android Studio 會在背景使用名為 Android Debug Bridge (ADB) 的工具。這項指令列工具已整合至 Android Studio,可為執行中的 app 提供 breakpoints 等 debugging 功能。進行 debugging 的工具通常稱為 debugger。
如要將 debugger 用於或附加至 app,您無法像往常一樣依序點選「Run」>「Run ‘app’」執行 app,而是改為「Run」 >「Debug ‘app’」。

在 project 中新增 breakpoints
請執行下列步驟,觀察 breakpoints 的實際運作情形:
- 找到您希望中斷動作的 line number,點選旁邊的空白以新增 breakpoint。line number 旁邊會出現一個點,且該行程式碼會被 highlighted。

- 利用「Run」(執行) >「Debug ‘app’」或工具列中的圖示執行附有 debugger 的 app:


一旦啟動 app,系統會 highlighted 有效的 breakpoint。

先前已開啟 Logcat 視窗的某個畫面底部已開啟「Debug」分頁。

左側是 functions list,與堆疊追蹤(stack trace)中顯示的 list 相同。右側是一個窗格,可讓您查看目前 function (即 division()
) 中個別變數(variables)的值(value)。您也可以透過頂端的按鈕,在程式暫停執行期間進行瀏覽。最常用的按鈕是「Step Over」(不進入),用來執行 highlighted 的單行程式碼。

請按照下列步驟操作,對程式碼進行 debug:
- 到達 breakpoint 後,第 19 行 (宣告
numerator
變數) 會 highlighted,但尚未執行。使用「Step Over」(不進入) 按鈕執行第 19 行:現在將 highlighted 第 20 行。

- 在第 22 行設定 breakpoint。這就是發生除法的位置,也是堆疊追蹤(stack trace)回報 exception 的一行。

- 使用「Debug」視窗左側的「Resume Program」(繼續執行程式) 按鈕,前往下一個 breakpoint:
執行 division()
函式的其餘部分。

- 請注意,執行作業在第 17 行停止,未執行該行。

- 每個變數
numerator
和denominator
的值會顯示在其宣告旁邊。變數值會顯示在「Variables」分頁的 debug 視窗中。

- 再按下「Debug」視窗左側的「Resume Program」(繼續執行程式) 按鈕四次。每次迴圈暫停時觀察
numerator
和denominator
的值。在最後一個迭代作業中,numerator
應為60
,而denominator
應為0
。然而將60
除以0
並不符合數學規則!

這樣一來,您就能得知造成 bug 的確切程式碼行,並瞭解確切原因。和先前一樣,只要將程式碼重複的次數從 5
變更為 4
,即可修正 bug。
1 | fun division() { |
設定 breakpoints conditions
在上一節中,您必須逐一檢查迭代迴圈,直到分母為 0
。在較為複雜的 app 中,如果您的錯誤資訊較少,可能會很繁瑣。不過,如果您有一個假設 (例如,app 只有在分母為零時才會異常終止),則可以修改中斷點,限制只有在符合假設時才會觸及中斷點,這樣就不必逐一檢查迴圈迭代。
- 如有需要,請在重複迴圈中將
4
變更為5
,以重新回報錯誤。
1 | repeat(5) { |
- 在含有
repeat
陳述式的行上放置新的 breakpoints。

- 在紅色中斷點圖示上按一下滑鼠右鍵。選單會顯示數個選項,例如是否已啟用中斷點。停用的中斷點仍然存在,但不會在執行階段觸發。您也可以選擇新增 Kotlin 運算式,如果運算結果為 True,就會觸發中斷點。例如,如果使用
denominator > 3
運算式,則只有在初次疊代迴圈時,才會觸發中斷點。如果只想在 app 可能除以零時觸發中斷點,請將運算式設為denominator == 0
。中斷點的選項會如下所示:

- 依序點選「Run」>「Debug ‘app’」執行您的 app,並觀察是否已到達 breakpoints。

如您所見,分母已是 0
。只有符合條件時才會觸發 breakpoints,因此您不必逐一檢查程式碼,可節省時間和精力。

- 和先前一樣,您會看到錯誤是因為循環執行一行程式碼太多次所造成,此時分母設為
0
。
新增 Watches
如果想在 debugging 時監控特定值,並不需要在「Variables」分頁中搜尋該值,只要新增所謂的 Watches 即可監控特定變數。這些變數會顯示在 debug 窗格中。當執行暫停且該變數位於範圍內時,就會顯示在「Watches」窗格中。如此一來,處理大型 projects 時,就能提高 debugging 效率。您可以集中追蹤所有相關變數。
- 在「Debug」view 中,「Variables」窗格右側會顯示另一個名為「Watches」的空白窗格。按一下左上角的加號按鈕:
您可能會看到顯示「New Watch」的選單選項。

在提供的欄位中輸入變數名稱
denominator
,接著按一下 enter 鍵。依序按一下「Run >「Debug ‘app’」重新執行 app,這時您會發現以下情況:遇到 breakpoint 時,系統會在「Watches」窗格顯示
denominator
的值。
