1. 事前準備
到目前為止,大多數的新手開發人員可能已經會使用記錄陳述式進行偵錯。完成單元 1 後,您將學到如何解讀堆疊追蹤和研究錯誤訊息。雖然這兩種工具都是功能強大的偵錯工具,但現代 IDE 提供更多功能,讓您的偵錯流程更有效率。
在本課程中,您將瞭解 Android Studio 整合的偵錯工具、如何暫停執行應用程式,以及一次執行單行程式碼,找出錯誤的確切來源。此外,您將學會如何使用一項稱為「Watches」的功能以及如何追蹤特定變數,而不必新增特定的記錄陳述式。
必要條件
- 您已瞭解如何在 Android Studio 中瀏覽專案。
- 熟悉 Kotlin 記錄功能。
課程內容
- 如何將偵錯工具附加到運作中的應用程式。
- 使用中斷點來暫停執行中的應用程式,逐行檢查程式碼。
- 將條件運算式加入中斷點以節省偵錯時間。
- 在「Watches」窗格中新增變數,以輔助偵錯。
軟硬體需求
- 已安裝 Android Studio 的電腦。
2. 建立新專案
我們不會一開始就對複雜的大型應用程式進行偵錯,而是會從空白專案著手並介紹一些錯誤程式碼,藉此展示 Android Studio 中的偵錯工具。
建立新的 Android Studio 專案,即可開始使用。
- 在「Select a Project Template」(選取專案範本) 畫面中選擇「Blank Activity」(空白活動)。
- 將應用程式命名為「Debugging」,接著確認語言已設為 Kotlin,其他項目則保持不變。
- 系統將開啟一項新的 Android Studio 專案,並顯示一個名為
MainActivity.kt
的檔案。
回報錯誤
還記得單元 1 中偵錯課程的除以零範例嗎?在迴圈的最終疊代中,應用程式嘗試執行除以零時,因為不可能除以零,因此應用程式當機,並彈出 java.langArithmeticException
。藉由檢查堆疊追蹤找出該錯誤並予以解決,並且使用記錄陳述式驗證該假設。
由於您已經熟悉那個範例,因此將用於示範中斷點的使用方式。中斷點會逐行處理程式碼,不必先新增記錄陳述式或重新執行應用程式。
- 開啟
MainActivity.kt
,並將程式碼替換為以下程式碼:
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
public val TAG = "MainActivity"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
division()
}
fun division() {
val numerator = 60
var denominator = 4
repeat(5) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
}
- 執行應用程式。觀察應用程式是否如預期當機。
3. 透過中斷點進行偵錯
瞭解記錄功能後,您已學會如何有策略地放置記錄,以便識別錯誤及驗證問題是否已修正。然而,在面對並非您導入的錯誤時,我們未必能明確得知要將記錄陳述式放置在何處,或是要輸出哪些變數。通常,您只能在執行階段找到這項資訊。
fun division() {
val numerator = 60
var denominator = 4
repeat(5) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
此時,中斷點就能發揮功效。即使您已根據堆疊追蹤中的資訊大致推斷出造成錯誤的原因,您仍可在某行程式碼新增中斷點做為停止訊號。一旦觸及中斷點,系統就會暫停執行程式碼,讓您可以在執行階段使用其他偵錯工具,以便詳細瞭解實際情況並判斷問題。
附加偵錯工具
Android Studio 會在背景使用名為 Android Debug Bridge (ADB) 的工具。這項指令列工具已整合至 Android Studio,可為執行中的應用程式提供中斷點等偵錯功能。進行偵錯的工具通常稱為偵錯工具。
如要將偵錯工具用於或附加至應用程式,您無法像往常一樣依序點選「Run」(執行) >「Run」(執行) 執行應用程式,而是改為「Run」(執行) >「Debug 'app'」(對「應用程式」進行偵錯)。
在專案中新增中斷點
請執行下列步驟,觀察中斷點的實際運作情形:
- 找到您希望中斷動作的行號,點選旁邊的空白以新增中斷點。行號旁邊會出現一個點,且該行程式碼會醒目顯示。
- 利用「Run」(執行) >「Debug 'app'」(對「應用程式」進行偵錯) 或工具列中的 圖示,執行附有偵錯工具的應用程式。應用程式啟動後,您會看到像這樣的畫面:
一旦啟動應用程式,系統會醒目顯示有效的中斷點。
先前已開啟 Logcat 視窗的某個畫面底部已開啟「Debug」分頁。
左側是函式清單,與堆疊追蹤中顯示的清單相同。右側是一個窗格,可讓您查看目前函式 (即 division()
) 中個別變數的值。您也可以透過頂端的按鈕,在程式暫停執行期間進行瀏覽。最常用的按鈕是「Step Over」(不進入),用來執行醒目顯示的單行程式碼。
請按照下列步驟操作,對程式碼進行偵錯:
- 到達中斷點後,第 19 行 (宣告
numerator
變數) 會醒目顯示,但尚未執行。使用「Step Over」(不進入) 按鈕執行第 19 行。現在將醒目顯示第 20 行。
- 在第 22 行設定中斷點。這就是發生除法的位置,也是堆疊追蹤回報例外狀況的一行。
- 使用「Debug」(偵錯) 視窗左側的「Resume Program」(繼續執行程式) 按鈕,前往下一個中斷點。執行
division()
函式的其餘部分。
- 請注意,執行作業在第 17 行停止,未執行該行。
- 每個變數
numerator
和denominator
的值會顯示在其宣告旁邊。變數值會顯示在「Variables」分頁的偵錯視窗中。
- 再按下「Debug」(偵錯) 視窗左側的「Resume Program」(繼續執行程式) 按鈕四次。每次迴圈暫停時觀察
numerator
和denominator
的值。在最後一個疊代作業中,numerator
應為60
,而denominator
應為0
。然而將 60 除以 0 並不符合數學規則!
這樣一來,您就能得知造成錯誤的確切程式碼行,並瞭解確切原因。和先前一樣,只要將程式碼重複的次數從 5
變更為 4
,即可修正錯誤。
fun division() {
val numerator = 60
var denominator = 4
repeat(4) {
Log.v(TAG, "${numerator / denominator}")
denominator--
}
}
4. 設定中斷點條件
在上一節中,您必須逐一檢查疊代迴圈,直到分母為 0。在較為複雜的應用程式中,如果您的錯誤資訊較少,可能會很繁瑣。不過,如果您有一個假設 (例如,應用程式只有在分母為零時才會異常終止),則可以修改中斷點,限制只有在符合假設時才會觸及中斷點,這樣就不必逐一檢查迴圈疊代。
- 如有需要,請在重複迴圈中將
4
變更為5
,以重新回報錯誤。
repeat(4) {
...
}
- 在含有
repeat
陳述式的行上放置新的中斷點。
- 在紅色中斷點圖示上按一下滑鼠右鍵。選單會顯示數個選項,例如是否已啟用中斷點。停用的中斷點仍然存在,但不會在執行階段觸發。您也可以選擇新增 Kotlin 運算式,如果運算結果為 True,就會觸發中斷點。例如,如果使用
denominator > 3
運算式,則只有在初次疊代迴圈時,才會觸發中斷點。如果只想在應用程式可能除以零時觸發中斷點,請將運算式設為denominator == 0
。中斷點的選項會如下所示:
- 依序點選「Run」>「Debug 'app'」執行您的應用程式,並觀察是否已到達中斷點。
如您所見,分母已是 0。只有符合條件時才會觸發中斷點,因此您不必逐一檢查程式碼,可節省時間和精力。
- 和先前一樣,您會看到錯誤是因為循環執行一行程式碼太多次所造成,此時分母設為 0。
新增 Watches
如果想在偵錯時監控特定值,並不需要在「Variables」分頁中搜尋該值,只要新增所謂的 Watches 即可監控特定變數。這些變數會顯示在偵錯窗格中。當執行暫停且該變數位於範圍內時,就會顯示在「Watches」窗格中。如此一來,處理大型專案時,就能提高偵錯效率。您可以集中追蹤所有相關變數。
- 在「Debug」檢視畫面中,「Variables」窗格右側會顯示另一個名為「Watches」的空白窗格。按一下左上角的加號 按鈕。您可能會看到顯示「New Watch」的選單選項。
- 在提供的欄位中輸入變數名稱
denominator
,接著按一下 enter 鍵。 - 依序按一下「Run」(執行) >「Debug 'app'」(對「應用程式」進行偵錯) 重新執行應用程式,這時您會發現以下情況:遇到中斷點時,系統會在「Watches」窗格顯示分母的值。
5. 恭喜
摘要 :
- 您可以設定暫停執行應用程式的中斷點。
- 執行暫停時,您可以「跳過」只執行單一行程式碼。
- 您可以設定條件陳述式,根據 Kotlin 運算式觸發中斷點。
- Watches 可讓您在偵錯時將感興趣的變數分組。