程式除錯是程式投入執行之前,使用手工或編譯程式等方法進行的測試,z主要用以修正語法錯誤和邏輯錯誤。程式除錯是保證計算機資訊系統正確性的必不可少的步驟。 在Flutter應用開發中,Android Studio和VSCode是兩種比較常見的整合開發環境,因此專案除錯也圍繞這兩款IDE進行。Android Studio為Flutter提供完整的整合IDE體驗,因此Android的除錯技巧對於Flutter來說也是適用的。在 Flutter 中,除錯程式碼主要分為輸出日誌、斷點除錯和佈局除錯 3 類,因此Flutter的除錯也將圍繞這 3 個主題。
Android Studio
輸出日誌
為了便於跟蹤和記錄應用的執行情況,我們在開發時通常會在一些關鍵步驟輸出日誌(Log),在Flutter中我們使用 print 函式在控制檯列印出相關的上下文資訊。通過這些資訊,就可以定位程式碼中可能出現的問題。不過,由於涉及 I/O 操作,使用 print 來列印資訊會消耗較多的系統資源。同時,這些輸出資料很可能會暴露 App 的執行細節,所以我們在釋出正式版時還需要遮蔽掉這些輸出。
不過最工程化的做法是讀取專案配置檔案,根據執行環境來開啟日誌除錯功能。為了根據不同的執行環境來開啟日誌除錯功能,我們可以使用 Flutter 提供的debugPrint 來代替 print。debugPrint 函式同樣會將訊息列印至控制檯,但與 print 不同的是,它提供了定製列印的能力。也就是說,我們可以向 debugPrint 函式,賦值一個函式宣告來自定義列印行為。
比如在下面的程式碼中,我們將 debugPrint 函式定義為一個空函式體,這樣就可以實現一鍵取消列印的功能了。
debugPrint = (String message, {int wrapWidth}) {};//空實現
複製程式碼
在 Flutter 中,我們可以使用不同的 main 檔案來表示不同環境下的入口。同樣,在Flutter開發中,可以通過 main.dart 與 main-dev.dart,去分別定義生產環境與開發環境不同的列印日誌行為。
在下面的例子中,我們將生產環境的 debugPrint 定義為空實現,將開發環境的 debugPrint 定義為同步列印資料,如下所示。
//main.dart
void main() {
// 將debugPrint指定為空的執行體, 所以它什麼也不做
debugPrint = (String message, {int wrapWidth}) {};
runApp(MyApp());
}
//main-dev.dart
void main() async {
// 將debugPrint指定為同步列印資料
debugPrint = (String message, {int wrapWidth}) => debugPrintSynchronously(message, wrapWidth: wrapWidth);
runApp(MyApp());
}
複製程式碼
可以看到,在程式碼實現上,我們只要將應用內所有的 print 都替換成 debugPrint,就可以滿足開發環境下打日誌的需求,也可以保證生產環境下應用的執行資訊不會被意外列印。
斷點除錯
輸出日誌固然方便,但如果要想獲取更為詳細,或是粒度更細的上下文資訊,靜態除錯的方式非常不方便。這時,我們需要更為靈活的動態除錯方法,即斷點除錯。斷點除錯可以讓程式碼在目標語句上暫停,讓程式逐條執行後續的程式碼語句,來幫助我們實時關注程式碼執行上下文中所有變數值的詳細變化過程。
Android Studio 提供了斷點除錯的功能,除錯 Flutter 應用與除錯原生 Android 程式碼的方法完全一樣,具體可以分為三步,即標記斷點、除錯應用、檢視資訊。
下面以 Flutter 預設的計數器應用模板為例,觀察程式碼中 _counter 值的變化,體會斷點除錯的全過程。
首先是標記斷點。既然我們要觀察 _counter 值的變化,因此在介面上展示最新的 _counter 值時新增斷點,去觀察其數值變化是最理想的。因此,我們在行號右側點選滑鼠,可以把斷點載入到初始化 Text 控制元件所示的位置。
在下圖的例子中,我們為了觀察 _counter 在等於 20 的時候是否正常,還特意設定了一個條件斷點 _counter==20,這樣偵錯程式就只會在第 20 次點選計數器按鈕時暫停下來。

新增斷點後,對應的行號將會出現圓形的斷點標記,並高亮顯示整行程式碼。到此,斷點就新增好了。當然,我們還可以同時新增多個斷點,以便更好地觀察程式碼的執行過程。
接下來則是除錯應用了。和之前通過點選Run 按鈕的執行方式不同,這一次我們需要點選工具欄上的蟲子圖示,以除錯模式啟動 App,如下圖所示。


控制除錯工具區域主要用來控制除錯的執行情況,如下圖所示。


C 區用來指示當前斷點所包含的函式執行堆疊,D 區則是其堆疊中的函式幀所對應的變數。
佈局除錯
除了輸出日誌、斷點除錯,佈局分析也是開發中不可缺少的程式碼優化手段。藉助Flutter提供的Flutter Inspector 視覺化工具,可以幫助我們診斷佈局問題。開啟Android Studio,然後點選工具欄上的“Open DevTools”按鈕即可啟動 Flutter Inspector,如下圖所示。


VSCode
除了Android Studio外,VSCode也是一款比較常見的Flutter應用程式開發工具。使用VSCode提供的圖形化除錯介面,開發者可以很方便的進行Flutter應用的除錯工作。使用VSCode開啟Flutter專案,然後點選VSCode的斷點除錯按鈕即可開啟除錯,如下圖所示。
