Android Studio目前已經(jīng)成為開發(fā)Android的主要工具,用熟了可謂相當順手。作為開發(fā)者,調(diào)試并發(fā)現(xiàn)bug,進而解決,可是我們的看家本領(lǐng)。正所謂,工欲善其事必先利其器,和其他開發(fā)工具一樣,如Eclipse、Idea,Android Studio也為我們提供了強大的調(diào)試技巧,今天我們就來看看Android Studio中有關(guān)調(diào)試的技巧。
首先,來看看Android studio中為我們提供的調(diào)試面板(標準情況下):
點擊右上角Restore ‘Threads’View可先展示目前相關(guān)的線程信息:
android studio大體為我們提供了7個功能區(qū):
- 單步調(diào)試區(qū)
- 斷點管理區(qū)
- 求值表達式
- 線程幀棧區(qū)
- 對象變量區(qū)
- 變量觀察區(qū)
下面我們分別對這七個區(qū)域進行介紹。
單步調(diào)試區(qū)
該區(qū)提供了調(diào)試的主要操作,和你所熟知的一樣的,主要有:Step over、step into、force step into、step out、drop frame。
Show Execution Point
這里寫圖片描述
點擊該按鈕,光標將定位到當前正在調(diào)試的位置.
Step Over
這里寫圖片描述
單步跳過,點擊該按鈕將導致程序向下執(zhí)行一行。如果當前行是一個方法調(diào)用,此行調(diào)用的方法被執(zhí)行完畢后再到下一行。比如當前代碼是:
int num=10;
int min=Math.min(num,100);
System.out.println(min);
如果當前調(diào)試的是第二行,當點擊step over時,Math.min(num,100)方法先執(zhí)行完后跳到第三行.
Step Into
這里寫圖片描述
單步跳入,執(zhí)行該操作將導致程序向下執(zhí)行一行。如果該行有自定義的方法,則進入該方法內(nèi)部繼續(xù)執(zhí)行,需要注意如果是類庫中的方法,則不會進入方法內(nèi)部。
Force Step Into
這里寫圖片描述
強制單步跳入,和step into功能類似,主要區(qū)別在于:如果當前行有任何方法,則不管該方法是我們自行定義還是類庫提供的,都能跳入到方法內(nèi)部繼續(xù)執(zhí)行
Drop Frame
這里寫圖片描述
沒有好記的名字,大意理解為中斷執(zhí)行,并返回到方法執(zhí)行的初始點,在這個過程中該方法對應的棧幀會從棧中移除.換言之,如果該方法是被調(diào)用的,則返回到當前方法被調(diào)用處,并且所有上下文變量的值也恢復到該方法未執(zhí)行時的狀態(tài)。簡單的舉例來說明:
public class DebugDemo {
private String name = "default";
public void alertName() {
System.out.println(name);
debug();
}
public void debug() {
this.name = "debug";
}
public static void main(String[] args) {
new DebugDemo().alertName();
}
}
當你在調(diào)試debug()時,執(zhí)行該操作,將回調(diào)到debug()被調(diào)用的地方,也就是alertName()方法。如果此時再繼續(xù)執(zhí)行drop frame,將回調(diào)到alertName()被調(diào)用的地方,也就是main().
Force Run to Cursor
這里寫圖片描述
非常好用的一個功能,可以忽視已經(jīng)存在的斷點,跳轉(zhuǎn)到光標所在處.舉個簡單例子說明下:
比如現(xiàn)在第10行,此時我想調(diào)試18行而又不想一步一步調(diào)試,能不能一次到位呢?我們只需要將光標定位到相應的位置,然后執(zhí)行Force Run to Cursor即可:
Evaluate expression
這里寫圖片描述
點擊該按鈕會在當前調(diào)試的語句處嵌入一個交互式解釋器,在該解釋器中,你可以執(zhí)行任何你想要執(zhí)行的表達式進行求值操作。比如,我們在調(diào)試時執(zhí)行到以下代碼:
此時執(zhí)行Evaluate Expression,就相當于在調(diào)試行之前嵌入了一個交互式解釋器,那么在該解釋器中我們能做什么呢?在這里,我們可以對result進行求值操作:對著你想要求值得位置點擊鼠標右鍵,選擇evaluate Expression.此時會顯示如下:
在彈出的輸入框中輸入求值表達式,比如這里我們輸入Math.min(result,50),如下圖
點擊執(zhí)行,我們發(fā)現(xiàn)在Result中已經(jīng)輸出了結(jié)果,如下:
斷點管理區(qū)
Return
這里寫圖片描述
點擊該按鈕會停止目前的應用,并且重新啟動.換言之,就是你想要重新調(diào)試時,可以使用該操作,嗯,就是重新來過的意思.
Pause Program
這里寫圖片描述
點擊該按鈕將暫停應用的執(zhí)行.如果想要恢復則可以使用下面提到的Resume Program.
Resume Program
這里寫圖片描述
該操作有恢復應用的含義,但是卻有兩種行為:
- 在應用處在暫停狀態(tài)下,點擊該按鈕將恢復應用運行.
- 在很多情況下,我們會設(shè)置多個斷點以便調(diào)試。在某些情況下,我們需要從當前斷點移動到下一個斷點處,兩個斷點之間的代碼自動被執(zhí)行,這樣我們就不需要一步一步調(diào)試到下一個斷點了,省時又省力。舉例說明:
public void test(){
test1();
...
test2();
}
假設(shè)我們分別在第2行和第4行添加了斷點。如果此時我們調(diào)試在第2行,此時點擊執(zhí)行該操作,當前調(diào)試位置會自動執(zhí)行到第4行,也就是第2到第4行之間的代碼會自動被執(zhí)行。
Stop
這里寫圖片描述
點擊該按鈕會通過相關(guān)的關(guān)閉腳本來終止當前進程.換言之,對不同類型的工程可能有不同的停止行為,比如:對普通的Java項目,點擊該按鈕意味著退出調(diào)試模式,但是應用還會執(zhí)行完成.而在Android項目中,點擊該按鈕,則意味這app結(jié)束運行.
這里我們以一個普通的JAVA工程為例:
此時如果我們執(zhí)行停止操作,發(fā)現(xiàn)程序退出調(diào)試模式,并正常執(zhí)行完畢,Console中結(jié)果如下:
View Breakpoints
這里寫圖片描述
點擊該按鈕會進入斷點管理界面,在這里你可以查看所有斷點,管理或者配置斷點的行為,如:刪除,修改屬性信息等:
Mute Breakpoints
這里寫圖片描述
使用該按鈕來切換斷點的狀態(tài):啟動或者禁用.在調(diào)試過程中,你可以禁用暫時禁用所有的斷點,已實現(xiàn)應用正常的運行.該功能非常有用,比如當你在調(diào)試過程中,突然不想讓斷點干擾你所關(guān)心的流程時,可以臨時禁用斷點.
Get thread dump
這里寫圖片描述
獲取線程Dump,點擊該按鈕將進入線程Dump界面:
借此我們順便介紹一下dump界面:
解析來我們來認識一下線程的類型,表示為不同的圖標:
| 線程狀態(tài)描述 | 圖標 |
|---|---|
| Thread is suspended. | 這里寫圖片描述
|
| Thread is waiting on a monitor lock. | 這里寫圖片描述
|
| Thread is running. | 這里寫圖片描述
|
| Thread is executing network operation, and is waiting for data to be passed. | 這里寫圖片描述
|
| Thread is idle. | 這里寫圖片描述
|
| Event Dispatch Thread that is busy. | 這里寫圖片描述
|
| Thread is executing disk operation. | 這里寫圖片描述
|
Settings
這里寫圖片描述
點擊該按鈕將打開有關(guān)設(shè)置的列表:
我們對其中的幾個進行說明:
Show Values Inline
調(diào)試過程中開啟該功能,將會代碼右邊顯示變量值,即下圖中紅框所示部分:
Show Method Return Values
調(diào)試過程中啟用該功能,將在變量區(qū)顯示最后執(zhí)行方法的返回值.舉個例子來說,首先,關(guān)閉該功能,我們調(diào)試這段代碼并觀察其變量區(qū):
開啟該功能之后,再來觀察變量區(qū)的變化:
繼續(xù)往下調(diào)試:
繼續(xù)往下調(diào)試:
這個功能簡直是棒極了,在調(diào)試一段代碼,并想看該代碼中最后調(diào)用方法的最終結(jié)果時就非常有用了.
Auto-Variables Mode
開啟這個功能后,idea的Debugger會自動評估某些變量,大概就是當你執(zhí)行在某個斷點時,Debugger會檢測當前調(diào)試點之前或者之后的變量的狀態(tài),然后在變量區(qū)選擇性輸出.舉個例子來說明,未開啟該功能之前,變量區(qū)輸出所有的變量信息:
開啟之后,當你調(diào)試到第13行時,Debugger檢測到num變量在之后沒有被使用,那么在變量區(qū)就不會輸出該變量的信息.
Sort values alphabetically
開啟這個功能的化,變量區(qū)中的輸出內(nèi)容會按照按字母順序進行排序,很簡單,不常用,還是按照默認的順序好.
Help
這里寫圖片描述
這個不用說了,有任何不明白的都可以查看官方幫助文檔,這是我見到最好的文檔之一.
其他幾個操作:Settings,Pin,Close留給各位自己去使用.
修改變量值
在調(diào)試過程中,我們可以方便的修改某個變量的值,如下:
在上圖中,當前result的值經(jīng)過計算為10,這里我們通過Set Value將其計算結(jié)果修改為100.
變量觀察區(qū)
該區(qū)域?qū)@示你所感興趣的變量的值。在調(diào)試模式下,你可以通過Add to Watches將某個變量添加到觀察區(qū),該值的變化將會在變量觀察區(qū)顯示。操作如下:
這里我們對name比較感興趣,希望看到它的值的變化情況,因此我們將其“特殊關(guān)照”。需要注意,此時因為name是成員變量,因此在對象觀察區(qū)也可看到該值。如果是局部變量,無疑只能用這種方式了。
斷點的分類
到目前為止,我們已經(jīng)簡單的介紹了調(diào)試功能區(qū),斷點管理區(qū),求值表達式,這三個區(qū)域的功能。在上面,我們不斷的提到了斷點一次,但是斷點是什么呢?想必大部分人已經(jīng)知道了,我們這里在簡單的說明下:
斷點是調(diào)試器的功能之一,可以讓程序暫停在需要的地方,幫助我們進行分析程序的運行過程。
在Android Studio中,斷點又被以下五類:
- 條件斷點
- 日志斷點
- 異常斷點
- 方法斷點
- 屬性斷點
其中方法斷點是我們最熟悉的斷點類型,相信沒有人不會。下面我們著重介紹其他四種類型的斷點。
條件斷點
所謂的條件斷點就是在特定條件發(fā)生的斷點,也就是,我們可將某個斷點設(shè)置為只對某種事件感興趣,最典型的應用就是在列表循環(huán)中,我們希望在某特定的元素出現(xiàn)時暫停程序運行。比如,現(xiàn)在我們有個list中,其中包含了q,1q,2q,3q四個元素,我們希望在遍歷到2q時暫停程序運行,那么需要進行如下操作:
在需要的地方添加斷點,如下:
斷點處左鍵單擊,在Condition處填寫過濾條件.此處我們只關(guān)心2q,因此填寫s.equals("2q")
日志斷點
該類型的斷點不會使程序停下來,而是在輸出我們要它輸出的日志信息,然后繼續(xù)執(zhí)行。具體操作如下:
同樣在斷點處左鍵單擊,在彈出的對話框中取消選中Suspend。
在彈出的控制面板中,選中Log evaluated expression,然后再填寫想要輸出的日志信息,如下:
當調(diào)試過程遇到該斷點將會輸出結(jié)果,如下:
異常斷點
所謂的異常斷點就是在調(diào)試過程中,一旦發(fā)生異常(可以指定某類異常),則會立刻定位到異常拋出的地方。比如在調(diào)試異常中,我們非常關(guān)注運行時異常,希望在產(chǎn)生任何運行異常時及時定位,那么此時就可以利用該類型異常,在上線之前,進行異常斷點調(diào)試非常有利于減少正式環(huán)境中發(fā)生crash的幾率。
在管理斷點面板中,點擊+
在彈出的下拉選擇列表中,我們選擇Java Exception Breakpoints
這里我們選中Search By Name,在下面的輸入框中輸入我們所關(guān)心的異常類型。此處我們關(guān)心NullPointerException,在調(diào)試過程一旦發(fā)生NullPointerException,調(diào)試器就會定位到異常發(fā)生處。
方法斷點
這里寫圖片描述
(略過吧,應該沒人不知道了)
Filed WatchPoint
這里寫圖片描述
Filed WatchPoint是本質(zhì)上是一種特殊的斷點,也稱為屬性斷點:當我們某個字段值被修改的時候,程序暫停在修改處。通常在調(diào)試多線程時尤為可用,能幫我們及時的定位并發(fā)錯誤的問題。其使用和添加普通的斷點并無不同,斷點圖標稍有不同
調(diào)試的兩種方式
到目前,調(diào)試的相關(guān)基礎(chǔ)我們已經(jīng)介紹完了,但是不少童鞋對Android Studio中這兩個按鈕感到困惑:Debug和Attach process。
這里我們就簡單介紹一下這兩者的區(qū)別:
- Debug:以調(diào)試模式安裝運行,斷點可以在運行之前設(shè)置,也可在運行后設(shè)置,是多數(shù)人最常用的調(diào)式方式
- Attach process:和Debug方式相比,能夠?qū)⒄{(diào)試器attach到任何正在運行的進程。比如,我們可以通過attach process到想要調(diào)試的進程。然后,在需要的地方設(shè)置相關(guān)斷點即可。
在具體調(diào)試過程,自行酌情選擇即可。后面,我會帶大家一步一步調(diào)試Android的Framework相關(guān)的源碼,參見:
自己動手編譯最新Android源碼及SDK及自己動手調(diào)試Android源碼