介紹frames删豺、threads椭微、evaluate的使用,斷點(diǎn)的一些屬性以及條件斷點(diǎn)之众、日志斷點(diǎn)拙毫、異常斷點(diǎn)等使用場(chǎng)景,幫助提高debug效率
跳過單步調(diào)試的stepOver stepInto等基礎(chǔ)調(diào)試棺禾,從上一幅圖開始缀蹄。
frames查看幀調(diào)用關(guān)系
圖中右邊箭頭指著的圖標(biāo)用來控制是否顯示frames。
左邊的箭頭指著的是調(diào)用關(guān)系膘婶,從Debug的frames也可以看到:onClick是在performClick中調(diào)用的缺前,同時(shí)可以看到前面是由ActivityThread調(diào)用。
即使沒有導(dǎo)入frameWork的源碼,從這里點(diǎn)進(jìn)去悬襟,也是可以看到ActivityThread(frameWork層)的源碼的P坡搿!脊岳!(just a joke肆良,只能看看,不能調(diào)試frameWork)
通過這種方式也可以看到activityThread逸绎,可以看到app的入口main函數(shù)惹恃,就和java的public static void main一樣!
順便看看驗(yàn)證下ui線程的Looper也是要prepare loop的棺牧,只是activityThread在main函數(shù)里面提前做了罷了巫糙。
Thread查看線程信息
這里開了2個(gè)線程來執(zhí)行doSomeTask函數(shù),然后在deSomeTask那里斷點(diǎn)颊乘,從debug的Threads可以看到除了Thread-154参淹,另外還有個(gè)Thread-155也是被斷到了的醉锄,把斷點(diǎn)放開后會(huì)接著由155線程執(zhí)行doSomeTask。而且從這里我們也可以意識(shí)到這是多線程訪問浙值,bug可能來源于線程同步未做好恳不。
evaluate計(jì)算運(yùn)行到斷點(diǎn)時(shí)的相關(guān)狀態(tài)
evaluate就是左邊箭頭指著的像計(jì)算器的那個(gè)小圖標(biāo)。
當(dāng)運(yùn)行到斷點(diǎn)的時(shí)候开呐,點(diǎn)擊evaluate,彈出左邊的彈框烟勋,輸入要計(jì)算的表達(dá)式,如當(dāng)前的線程信息或者其他你想知道的東西筐付。如圖可以看到當(dāng)前線程id是155卵惦,所以不是ui線程(threadId = 1),如果在這個(gè)函數(shù)執(zhí)行ui操作會(huì)拋出異常(非ui線程更新ui)瓦戚。
這個(gè)操作簡(jiǎn)直666啊沮尿,如果以前按單步調(diào)試想看某一項(xiàng)信息就比如threadId,必須要寫一行代碼较解,重新編譯運(yùn)行
long threadId = Thread.currentThread().getId();
然后斷點(diǎn)到這里看threadId變量的值是多少畜疾,而且調(diào)試完了之后還需要把這行代碼刪除掉,用evaluate簡(jiǎn)直太方便印衔。
幾種特殊斷點(diǎn)
點(diǎn)擊紅色箭頭或者右鍵黑色箭頭指向的斷點(diǎn)都可以彈出右邊的彈框:設(shè)置斷點(diǎn)的各種屬性庸疾。
粉紅色的Suspend指是否掛起,如果勾選了(默認(rèn)suspend)当编,執(zhí)行到斷點(diǎn)處會(huì)停下。
藍(lán)色的Condition指掛起的條件徒溪,勾選后忿偷,符合所寫表達(dá)式的條件才會(huì)停下。
黃色的Evaluate and log指會(huì)將evaluate的值打印到console上臊泌。
紅色的filters指Class的過濾鲤桥,比如只看某個(gè)類的斷點(diǎn)或者不看某個(gè)類的斷點(diǎn)。
不同的斷點(diǎn)方式由不同的斷點(diǎn)條件組合而成渠概。
- 條件斷點(diǎn)
勾選Condition茶凳,然后寫上需要的條件,比如圖中我覺得Bug很可能出現(xiàn)在isRequestWeb = false的情況播揪,我就把condition寫上去贮喧,執(zhí)行時(shí)忽略掉為true的情況,專心查看為flase的情況猪狈。
又比如循環(huán)遍歷的時(shí)候箱沦,不想一直手動(dòng)跳到下一個(gè)斷點(diǎn)查看每一個(gè)循環(huán)體,就可以寫一個(gè)自己想要的條件斷下來雇庙。 -
日志斷點(diǎn)
有的時(shí)候改bug谓形,不確定問題在哪兒灶伊,不能瞎J8到處斷點(diǎn),一步一步的調(diào)試寒跳,這樣太低效了聘萨。這時(shí)就需要打日志出來看。
但是log的代碼寫上bug改完后童太,還要把這些log刪除掉米辐,比較麻煩。更麻煩的是加寫一句log康愤,又要重新編譯一次儡循。這時(shí)就需要使用日志斷點(diǎn)。
打上斷點(diǎn)征冷,把Suspend打鉤取消掉择膝,這樣程序不會(huì)被斷點(diǎn)斷下來。然后evaluate and log寫上需要打印的日志即可检激。
如圖無需加代碼肴捉,無需重新編譯。直接再觸發(fā)一次斷點(diǎn)叔收,在debug的Console那里就可以看到運(yùn)行的日志(之前演示多線程的例子齿穗,這里就是典型的線程同步的問題,導(dǎo)致請(qǐng)求了2次網(wǎng)絡(luò))
-
異常斷點(diǎn)
看斷點(diǎn)方式那幅圖綠色的箭頭指向的+饺律,顯示出另外幾種斷點(diǎn)
其中第一個(gè)是方法斷點(diǎn):也就是斷點(diǎn)打在方法上窃页,斷點(diǎn)的樣子會(huì)像左邊的圖標(biāo)那樣(和在方法體里的第一行代碼打斷點(diǎn)差不多)。
第二種是field斷點(diǎn):用來查看字段的訪問(和在getter setter斷點(diǎn)相似)
第三種java異常斷點(diǎn)好像有點(diǎn)雞肋的复濒,程序異常的時(shí)候脖卖,可以通過異常斷點(diǎn)查看是哪個(gè)地方出問題了。但是崩潰的時(shí)候巧颈,也可以通過AS的崩潰日志鎖定出問題的地方畦木。
選中第三個(gè)java exception 斷點(diǎn),在里面輸入格式轉(zhuǎn)化出錯(cuò)的異常
OK后斷點(diǎn)里面就有這個(gè)format異常的斷點(diǎn)了砸泛。
圖中可以看到十籍,上面還可以選擇Any Exception,即只要是exception都會(huì)斷到唇礁。
強(qiáng)行寫一個(gè)NumberFormat異常勾栗,然后重新運(yùn)行,進(jìn)入debug模式盏筐,觸發(fā)異常:
String a = "12a";
try {
int b = Integer.parseInt(a);
} catch (NumberFormatException e) {
e.printStackTrace();
}
可以看到是MainActiviy的237行出現(xiàn)了NumberFormatException,點(diǎn)擊進(jìn)入到對(duì)應(yīng)行械姻,果然是那里的問題。
這里為了方便查看就把frames的調(diào)用關(guān)系隱藏掉了,點(diǎn)擊之前frames說的那個(gè)圖標(biāo)即可楷拳。
異常斷點(diǎn)可以結(jié)合各種filter使用绣夺,比如結(jié)合class Filter只查看MainActiviy里面的異常,或者不查看BinaryThree里面的異常欢揖,崩潰日志就做不到這一點(diǎn)陶耍。
后面的三種暫時(shí)也沒用到過,就跳過了她混。
- 其他
調(diào)試的花樣還有烈钞,比如在變量表里面setValue改變變量值、添加到watcher觀察等操作坤按。
總之一切為了提高效率毯欣!人生苦短~~