逮蝦戶!Android程式除錯竟簡單如斯

coder-pig發表於2018-12-07

逮蝦戶!Android程式除錯竟簡單如斯

PS:行吧,不用百度了,逮蝦戶是《頭文字D》的一首配樂《Deja vu》,中文諧音
“逮蝦戶”,飆車漂移專用BGM,有時音樂響起也暗示著:開車。

當然本節討論的不是開車,而是Android開發中老生常談的程式除錯。

一個開發仔的日常離不開:寫BUG和解BUG,特別是多人協作的時候,
幫別人擦屁股(解Bug)的情況屢見不鮮。另外,接盤別人的專案,著手解
Bug也能幫你快速的上手專案。綜上,修煉好「除錯」這門技能顯得尤為重要。
但是,但是感覺很多玩家還停留下無腦列印的階段,所以有了這篇文章。

筆者儘量以最精簡的方式來過一過Android除錯中的(qi)(ji)(yin)(qiao)。

逮蝦戶~


1.無腦靜態除錯

解釋下這個標題:

  • 無腦覺得哪裡有問題就列印哪裡
  • 靜態:每次想列印,都要去修改程式碼,然後重新執行程式。

適用於:想檢視變數的值在某一時刻是否異常!

接著來說下兩種常用的除錯方法:

Toast列印法

新手Android開發仔最愛除錯法,使用簡便,僅需一行程式碼,輕鬆列印:

Toast.makeText(MainActivity.this, "Toast除錯", Toast.LENGTH_SHORT).show();

方便是挺方便的,不過有一點要注意:Android 5.0後,如果把「訊息通知的許可權
關閉掉的話,部分機型是不會顯示Toast的!你還可以使用Snackbar來顯示值進行除錯:

Snackbar.make(父view, "Snackbar除錯", Snackbar.LENGTH_SHORT).show();

或者其他變通的方法,比如在頁面上新增一個TextView,把值直接顯示在文字框上。

Log日誌列印法

Toast除錯是挺爽的,但是有兩個問題:

  • 1.想除錯列印多個值的話,Toast會彈個不停,畢竟同一時刻只有「一個」Toast顯示在前臺;
  • 2.Toast間隔一段時間後會消失,即使你設定了Toast.LENGTH_LONG

可能你一走神,沒來得及看除錯的值,Toast就消失了。我們著實需要一種無需擔心除錯
結果消失的方法——「Log日誌列印法」,就是利用Android系統提供的Log類,在除錯
的地方,把日誌列印到「Logcat控制檯」上,使用方法也非常簡單:

Log.d("TAG", "Log除錯")

當程式碼執行到這一句的時候,就會在Logcat控制檯列印除錯資訊,另外Logcat預設
會列印出所有的日誌資訊,我們可以做一些過濾來定位到我們除錯的日誌資訊。
首先是:「日誌型別」,Android支援6種日誌型別,依次如下:

  • Verbose:詳細,所有型別的日誌資訊。
  • Debug:除錯,除錯用的日誌資訊。
  • Info:資訊,正常使用時需要關注的日誌資訊。
  • Warn:警告,可能有問題,但沒發生錯誤的日誌資訊。
  • Error:錯誤,執行時出現嚴重錯誤的日誌資訊。
  • Assert:斷言。

溫馨提示

不要上來就Error級別,我以前打Log全部用Log.e,原因是日誌資訊是紅色的,好看…
結果被組長屌了一頓,o(TωT)o ,覺得顏色不好看,你可以按照下述的操作進行自定義。

開啟「Settings」-> 「Editor」->「Colors Scheme」->「Android Logcat
選擇日誌型別,然後去掉勾選,然後點選選擇顏色色值

這是筆者配色方案,讀者可以自行調整為喜歡的顏色:

  • Assert:8F0005
  • Debug:0070BB
  • Error:FF0006
  • Info:48BB31
  • Verbose:BBBBBB
  • Warning:BBBB23

設定後的配色如圖所示:

行吧,知道可以通過Log類列印除錯和自定義Logcat配色,順帶也提提「日誌過濾」的姿勢吧。

  • 自定義Logcat日誌頭資訊的顯示內容:點選皮膚上的「Logcat Header」來設定日誌頭資訊

可選設定內容如下:

右側還可以「過濾日誌資訊」,支援正則,再右面是過濾特定日誌的選項。

如果覺得還不夠的話,可以點選最右側的「Edit Filter Configuration」來配置一個自己的過濾器。

另外,還可以對進行「日誌搜尋」,滑鼠點選Logcat中間區域獲得焦點,Ctrl + F 調出
搜尋工具欄,接著搜尋相關的日誌內容。

順帶提下Log類的一個容易忽略的小坑:

Log類只會列印4000個字元,超過部分不列印!!!

2.有腦動態除錯法

其實就是用Android Studio提供的Debug模式來程式除錯,相比起前面的
Toast列印法和Log日誌列印法,稍微複雜一點,要點學習成本,還有動腦子,
最重要是可以動態除錯,很多新手玩家貌似對這個都望而卻步,其實不難,待我
帶你九淺一深,em…由淺入深走一遭,來學學Android Studio Debug核心技巧。

1)基本的除錯流程

一般的除錯流程圖如下所示:(核心就是下斷點,單步除錯,值跟蹤

2)下斷點

先說說斷點,不是張敬軒的《斷點》,除錯時的斷點的作用是:

當程式執行到斷點所在的程式碼時,會暫停應用程式的執行,執行緒被掛起,然後
可以通過偵錯程式進行跟蹤。

下斷點的方式也很簡單,點選某行程式碼的左側,會出現如圖所示的小紅點。

這個小紅點就是斷點,而在AS中,又有著多種型別的斷點,帶你們過一遍吧:

  • 行斷點

就是上面這種,對特定行進行除錯時用到,點選行所在的左側邊欄即可設定。
右鍵點選這個斷點,會彈出如下所示的設定對話方塊:

如果你取消了Enabled勾選,斷點就處於如圖所示的禁用狀態:

  • 方法斷點

如果你把斷點下到一個方法前,斷點就會變成這樣:

這個就是方法斷點,一般用來檢查方法的「輸入引數」與「返回值」。

  • 變數斷點

有時我們對程式執行過程並不關心,而只關注某個變數的變化,可以在變數定義前加一個斷點。

在程式執行過程中,如果該變數的值發生改變,程式會自動停下來,並定位到變數值改變的地方,供開發者除錯。

另外,右鍵還可以設定斷點,Watch皮膚有兩個特有的選項,可按需勾選:

  • Field access:欄位被訪問時觸發斷點。
  • Field modification:欄位被修改時觸發斷點。
  • 條件斷點(斷點設定Condition)

有時會有這樣的場景:把斷點打到迴圈體的中,我們只關心特定迴圈次數下的執行情況。
比如一個迴圈10次的迴圈體,我們想知道迴圈到第8次時的執行情況,如果你不知道
條件斷點的話,你需要一直按「Run to Cursor」直到滿足我們的條件。比如下面的程式碼:

我們想知道當i = 8的時候,sum為多少,你需要一直按「Run to Cursor」

按7次,直到i = 9位置,如果用條件斷點,當迴圈體執行到某個條件才停下來,右鍵斷點,輸入如圖所示的等式條件:

然後可以發現,程式直接跳到i=8的時候才掛起,非常方便。

  • 日誌斷點

除錯的時候我們可以通過列印日誌的方式來定位異常程式碼大概位置,以縮小引發問題的範圍,然後
再使用斷點精確定位問題。如果是普通的列印日誌,我們需要等待重新構建程式,如果用「日誌斷點
就避免這個無意義的等待。使用日誌斷點非常簡單,右鍵斷點,去掉「Suspend」的勾選,會出現
如下所示的彈窗,勾選「Evaluate and log」在此輸入想輸出的內容。

執行除錯後,當執行到日誌斷點的時候可以看到控制檯輸出了對應的日誌資訊,而且程式正常執行,並不會掛起。

如果想檢視更詳細的資訊,比如斷點的位置和觸發時的堆疊資訊,可以勾選「“Breakpint hit” message」和「Stacktrace」,勾選後輸出內容會變得更詳細:

  • 臨時斷點

所謂的臨時斷點就是:觸發一次後就自動刪除的斷點。設定的方法有兩種:

  • 1.游標移到想打點的行,點選選單欄「Run」->「Toggle Temporary Line Breakpoint」,
    等價於快捷鍵:「Ctrl+Alt+Shift+F8
  • 2.更便捷的操作:按住Alt,滑鼠點選左側邊欄。

滑鼠點選後可以去掉臨時斷點,如果想把臨時斷點變成普通斷點,可以取消勾選
Remove once hit」的選項。

  • 異常斷點

用於監聽程式異常,一旦程式奔潰,直接定位到異常所在的確切位置。依次點選:
Run」->「View Breakpoints」開啟斷點檢視。點選「+」,然後選擇
Java Exception Breakpoints」,在彈出的視窗中輸入要除錯的異常:

除了設定異常斷點外,你在這裡看到專案設定的所有斷點,並進行斷點管理與配置
另外,你還可以設定自定義異常斷點,點選「4.Exception Breakpoints」自行配置即可。


3)進入除錯模式的另一種方式

大部分的同學除錯都是通過點選下面這個只小蟲子進入除錯模式。

這種方法有個缺點就是:每次都需要重新執行程式,可能有這樣的場景:把APP丟給測試
測試,然後出現了一個很稀有的BUG,此時你如果用普通的Debug模式,需要重啟APP,但是
Bug不一定能夠復現,這就很尷尬了。對於需要動態除錯的場景,可以「直接除錯正在執行的
Android程式
」,點選如下所示的另一個有小蟲子的圖示:

然後選擇要除錯的包名,就可以無需重啟應用直接進行除錯了:


4)除錯工具詳解

這裡把除錯工具劃分為如圖所示的五個區域一個個講解:

  • A區步進除錯工具
圖示 名稱 功能描述
顯示執行點 定位到當前正在除錯的斷點。
單步跳過 一步一步執行,遇到方法直接執行完方法,進入下一步,不會進入方法內部。
單步進入 一步一步執行,遇到方法且是自定義的方法,則進入方法內部,否則不會進入。
強制進入 遇到方法無論是自定義的還是官方類庫的,都會進入方法內部。
單步跳出 跳出當前進入的方法,返回方法呼叫處的下一行(也意味著方法被執行完畢)。
丟棄幀 如果你在某個方法內,執行完丟棄幀,當前方法會被中斷,返回方法被呼叫的
地方,變數的值也會重置。
執行到游標處 可以看做是臨時斷點,程式執行到當前游標所在行暫停。
計算表示式 支援在除錯過程中,通過賦值或表示式方式修改任意變數的值。

!!!注意:上面的執行到游標處是有個前提的:中途沒有斷點,如果你想強制執行到
游標處的話,你需要「Force Run to Cursor」,你可以通過下述兩種方式進行操作:

  • 1.游標處右鍵,選中「Force Run to Cursor」,如圖:

  • 2.使用快捷鍵:Ctrl + Alt + F9。
  • B區控制除錯工具
圖示 名稱 功能描述
繼續程式執行 程式執行到某個斷點暫停,如果有下一個斷點,點選後跳到這個斷點,
沒有的話,程式則繼續執行。
暫停程式執行 暫停程式執行。
終止程式執行 終止程式執行。
檢視斷點 可以檢視所有的斷點,管理與斷點配置
禁用所有斷點 切換所有斷點的狀態(啟用/禁用),禁用後,程式就不會觸發斷點。
獲得執行緒堆疊 顯示執行緒的相關資訊
恢復佈局 恢復到原始佈局
設定 除錯的相關配置,比如是否顯示執行方法後的返回值
  • C區幀除錯視窗

這裡的幀指的是:堆疊幀,一種用於「儲存資料」和「部分過程結果」的資料結構;
每次呼叫方法在堆疊中都會佔用一部分記憶體,單位是,隨著方法呼叫而建立。
每個堆疊幀中包括了:「傳入引數」、「返回地址」、「區域性變數」以及「對程式除錯提供支援的資訊」。一個執行緒包括多個堆疊幀。

檢視工具那裡可以以上下順序切換的方方式檢視幀(滑鼠直接點選也可以),最右側的漏斗圖示
點選後可以過濾掉:「非本應用的幀」。另外,你還可以右鍵堆疊幀,新增「步進過濾器」、
匯出執行緒」或「自定義執行緒顯示」。

  • D區變數區

在這個區域可以看到堆疊幀中當前所有的資料(方法引數、本地變數、例項變數)。
右鍵某個變數,可以進行「設定\複製變數值」,「跳轉到變數在程式碼中的位置」等操作。
一個常用的操作:選擇**「Add to Watches」**,單獨監視這個變數的變化。

  • E區監視視窗

除了前面這種右鍵新增監視的方法外,你還可以直接在E區點選「+」進行新增。

不止監控變數,還支援監控表示式,比如上面的i+1。
關於Android Debug除錯的基本操作大概就這些,多去實戰中歷練鞏固吧!


3.Android Wifi 無線除錯

其實還是要先電腦這個也非常簡單,安裝一個「ADB WIFI」的外掛,安裝後重啟:

然後把APP的除錯模式為「Usb Device

手機連線電腦,依次點選AS的選單欄:「Tools」->「ADB USB TO WIFI 」,然後左下角會出現:

一般來說,要掃描好久,建議自己看下手機ip,然後通過adb命令進行連結,示例如下:

adb connect 10.1.7.200:5555

# 出現下述資訊代表連線成功:
connected to 10.1.7.200:5555

連線成功後就可以拔掉資料線,進行無線除錯了。


4.利用Network Profiler抓包

Android Profiler是AS 3.0後引入的效能分析工具,而Network Profiler是其中一個用於網路分析的工具,
利用它我們直接抓包,而不需藉助第三方的抓包工具(比如Charles)進行分析除錯。
比較簡單,介面如下:

利用它可以進行很方便的抓包操作。


關於Android程式除錯的東西肯定不止這些,上述的算是基本功吧。
有更多除錯技巧歡迎在評論區留言~謝謝


參考文獻:


Tips:公號目前只是堅持發早報,在慢慢完善,有點心虛,只敢貼個小圖,想看早報的可以關注下~

相關文章