android實用除錯技巧
本文我們將講解android中的除錯技巧。程式除錯,是將編制的程式投入實際執行前,用手工或編譯程式等方法進行測試,修正語法錯誤和邏輯錯誤的過程。這是保證計算機資訊系統正確性的必不可少的步驟。在android開發過程中熟練的使用除錯技巧是一個很重要的方面。android的除錯技巧包括熟練使用android中的日誌API,自定義android日誌框架,通過gradle配置除錯日誌,android studio的除錯技巧等等。通過對本文的學習我們能夠對android中除錯技巧有一個大概的瞭解。
android中的列印API:
我們首先來看一下android中提供的列印日誌API:
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">android<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.util</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.Log</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.java</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
這個類比較常用的列印日誌的方法有5個,這5個方法都會把日誌列印到AndroidMonitor中,android中日誌分為五個級別:
-
Log.v(tag,message); //verbose模式,列印最詳細的日誌
-
Log.d(tag,message); //debug級別的日誌
-
Log.i(tag,message); //info級別的日誌
-
Log.w(tag,message); //warn級別的日誌
-
Log.e(tag,message); //error級別的日誌
其中tag和message分別是兩個String值.從android開發幫助文件中來看,tag和message的定義分別是:
tag:Used to identify the source of a log message. It usually identifies the class or activity where the log call occurs.
msg:The message you would like logged.
可看出tag用來標記log訊息的源頭的。而message則是這條log的內容.
- 一個簡單的Log API例子
Log demo程式碼:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 按鈕點選事件,列印各個級別的日誌 */</span> button6.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() { <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) { Log.v(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a verbose log!!!"</span>); Log.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a debug log!!!"</span>); Log.i(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a info log!!!"</span>); Log.w(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a warning log!!!"</span>); Log.e(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a error log!!!"</span>); } });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
好吧,我們點選按鈕,看一下AndroidMonitor中的列印結果:
<code class="hljs erlang-repl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">07</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.202</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>/<span class="hljs-function_or_atom" style="box-sizing: border-box;">uuch</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">com</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">android_activityanim</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">V</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">MainActivity</span>: <span class="hljs-function_or_atom" style="box-sizing: border-box;">this</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">is</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">a</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">verbose</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">log</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">07</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.202</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>/<span class="hljs-function_or_atom" style="box-sizing: border-box;">uuch</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">com</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">android_activityanim</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">D</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">MainActivity</span>: <span class="hljs-function_or_atom" style="box-sizing: border-box;">this</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">is</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">a</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">debug</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">log</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">07</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.202</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>/<span class="hljs-function_or_atom" style="box-sizing: border-box;">uuch</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">com</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">android_activityanim</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">I</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">MainActivity</span>: <span class="hljs-function_or_atom" style="box-sizing: border-box;">this</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">is</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">a</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">info</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">log</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">07</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.202</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>/<span class="hljs-function_or_atom" style="box-sizing: border-box;">uuch</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">com</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">android_activityanim</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">W</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">MainActivity</span>: <span class="hljs-function_or_atom" style="box-sizing: border-box;">this</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">is</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">a</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">warning</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">log</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">07</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">17</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">19</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">22</span>:<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16.203</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>-<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7530</span>/<span class="hljs-function_or_atom" style="box-sizing: border-box;">uuch</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">com</span>.<span class="hljs-function_or_atom" style="box-sizing: border-box;">android_activityanim</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">E</span>/<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">MainActivity</span>: <span class="hljs-function_or_atom" style="box-sizing: border-box;">this</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">is</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">a</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">error</span> <span class="hljs-function_or_atom" style="box-sizing: border-box;">log</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span><span class="hljs-exclamation_mark" style="box-sizing: border-box;">!</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
通過這種android自身Log API列印日誌的方式,是最常見的一種列印日誌的,除錯程式碼的方式,基本上所有的專案中你可能都會遇到這種日誌程式碼,前面的一篇文章中我也分析了Log日誌的部分原始碼,具體可參考我的:android原始碼解析之(六)–>Log
但是呢你會發現這時候列印的日誌格式比較簡陋,比如出現異常的時候我們想快速定位到程式碼在哪,這時候就比艱難了,所以下面我們講一下自定義日誌框架。
自定義android列印框架MLog:
前面我們發現使用Android原生的Log API列印的日誌格式比較簡陋,那麼可不可以定製化的顯示一些友好型的日誌資訊呢?答案是肯定的,在前面的文章中我介紹了一個自定義的日誌框架MLog,可參考我的:github專案解析(五)–>android日誌框架
關於MLog框架的使用方式,實現過程等已在文章中做過簡單的介紹,這裡就看一下其列印的日誌格式:
自定義按鈕點選事件:
- 在Application中初始化MLog框架
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 傳入為true,則表示執行列印操作,否則不顯示日誌 */</span> MLog.init(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
儘量可以在Application的onCreate方法中執行,這是App的程序起始方法。
- 在原始碼中執行列印日誌的操作
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 自定義按鈕的點選事件 */</span> button6.setOnClickListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> View.OnClickListener() { <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">onClick</span>(View v) { MLog.v(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a verbose log!!!"</span>); MLog.d(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a debug log!!!"</span>); MLog.i(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a info log!!!"</span>); MLog.w(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a warning log!!!"</span>); MLog.e(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"this is a error log!!!"</span>); } });</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
在AndroidMoitor中列印的日誌格式和內容:
這樣我們在點選日誌資訊的時候就能夠跳轉到這條日誌的程式碼列印位置,是不是很方便?而且如果覺得日誌格式不是很好的話,還可以定製化展示奧。
比如:
怎麼樣?是不是很好看了?
大多時候我們的App都有測試環境和正式環境兩種環境的,當切換環境的時候要求我們在測試環境列印日誌,則正式環境遮蔽日誌,通過程式碼也可以實現,但是比較麻煩,有沒有一個比較簡單的方法呢?答案是肯定的,可以通過配置gradle的方式配置在測試環境中列印日誌,在正式環境中遮蔽日誌列印操作。
gradle中配置正式測試列印框架:
我們知道在android開發過程中為了除錯程式碼經常在程式碼中新增一些日誌資訊,但是正式環境是不需要這些日誌資訊的,而且過得日誌列印操作也會對App的效能有影響。
一個比較好的辦法就是在App的測試環境中列印日誌資訊,在正式環境中遮蔽日誌資訊,那麼如何實現呢?通過程式碼麼?通過程式碼也是可以實現的,但是這樣顯得太原始了,其實android studio的gradle外掛已經提供了這樣的功能。
那麼如何通過gradle配置日誌列印資訊呢?
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">buildTypes { debug { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 顯示Log</span> buildConfigField <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"boolean"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LOG_DEBUG"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"true"</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//混淆</span> minifyEnabled <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Zipalign優化</span> zipAlignEnabled <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 移除無用的resource檔案</span> shrinkResources <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//載入預設混淆配置檔案</span> proguardFiles getDefaultProguardFile(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-android.txt'</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-rules.pro'</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//簽名</span> signingConfig signingConfigs.debug } release { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 不顯示Log</span> buildConfigField <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"boolean"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"LOG_DEBUG"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"false"</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//混淆</span> minifyEnabled <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//Zipalign優化</span> zipAlignEnabled <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 移除無用的resource檔案</span> shrinkResources <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//載入預設混淆配置檔案</span> proguardFiles getDefaultProguardFile(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-android.txt'</span>), <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'proguard-rules.pro'</span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//簽名</span> signingConfig signingConfigs.relealse } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li></ul>
在android studio的module的gradle配置檔案中,在buildTypes節點下可以配置自定義引數,這裡我們在debug版本中定義LOG_DEBUG為true,在release版本中定義LOG_DEBUG為false。這樣在編譯的時候就會在gradle的編譯類BuildConfig中生成成員變數:
<code class="hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">LOG_DEBUG</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
-
若是正式環境則LOG_DEBUG的值為false
-
若是測試環境則LOG_DEBUG的值為true
所以這時候可以通過LOG_DEBUG變數的值控制日誌是否列印。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** * 在Application的onCreate方法中初始化MLog日誌框架 * 並根據apk環境判斷是否顯示日誌資訊 */</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (BuildConfig.LOG_DEBUG == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>) { MLog.init(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> { MLog.init(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
我們實現的MLog框架的init方法
-
若傳入的值為true,則表示執行日誌列印操作,也就是可以顯示日誌資訊。
-
若傳入的值為false,則表示不執行日誌列印操作,也就是不顯示日誌資訊。
這樣我們就實現了在測試環境列印日誌,在正式環境中遮蔽日誌的操作。
android studio的除錯技巧:
寫程式碼的過程中不可避免有Bug,通常情況下除了日誌最直接的除錯手段就是debug;那麼你的除錯技術停留在哪一階段呢?僅僅是下個斷點單步執行嗎?你是否知道求值除錯,條件斷點,日誌斷點,方法斷點,異常斷點等除錯技巧麼?下面我們將介紹一下android studio中的除錯技巧。
除錯基礎
一般來說我們有兩種辦法除錯一個debuggable的apk;
-
設定好斷點,然後用debug模式編譯安裝這個app;
-
執行attach debugger to android process,即將debug程序新增到當前程序中。
一般比較常使用的debug方式是attach debugger to android process:
在執行按鈕右側兩個的帶有小蟲子的按鈕其實就是Attach Debugger to android process按鈕。
我們可以在啟動apk之後,直接下斷點,然後attach process到指定程序,條件觸發之後就可以直接進入除錯模式。
斷點除錯
斷點除錯是最基本操作,基恩的斷點除錯有以下的幾個常用的除錯命令:
-
F5跳轉內部執行
-
F6跳轉下一步
-
F8跳轉到下一個斷點
如何新增斷點?
直接在android studio中的Java原始碼左側,想除錯某一行程式碼的話,直接單擊若左側出現了一個小紅圈,則說明斷點已經新增好了:
當代碼處於debug模式,並且執行到此處的時候就會卡住在這裡。
執行斷點除錯
執行attach debugger to android process,當代碼執行到含有斷點的時候就可以將程式卡到斷點的程式碼了:
這時候我們可以看到在該行程式碼中可以看到相應的區域性變數值,執行F6走到下一步,執行F8,除錯到下一個斷點。
新增觀察變數
在除錯模式下,選擇變數,並右擊:
這時候選擇Add to watches,就可以將變數新增到觀察列表了。
表示式除錯:Evaluate Expression
這個除錯功能非常的實用,也是我最喜歡的功能,使用ctrl + u快捷鍵可以彈窗表示式除錯彈窗:
這個功能非常實用,可以在斷點處直接進入一個求值環境,在這裡你可以執行任何你感興趣的表示式可以在表示式除錯彈窗中寫任何java表示式,比如:
其他的比如在斷點處有一個物件object,如果你要檢視它的某個屬性很簡單,在Debug視窗就能看到,但是如果你想要執行它的某個方法看看結果是什麼呢?藉助這個可以實現。當然它的功能遠不止這麼多,相當於直接進入了一個 REPL環境,非常實用。
條件斷點
假設你的斷點在一個列表的迴圈裡面,可是你只對這個列表的某一個元素感興趣,只想在遇到這個元素的時候才斷下來;你是一直人肉 F9 直到滿足條件嗎?條件斷點就是滿足這種需求的,顧名思義,在特定條件下的斷點。使用起來也非常簡單,在你的斷點上滑鼠右鍵會出現一個小視窗,寫上條件即可。
其他斷點除錯方式
除了這裡的求值斷點,條件斷點,還有日誌斷點,異常斷點,方法斷點等,具體的可自行google哈。
總結:
-
android預設提供了Log API實現對日誌的列印功能;
-
可以實現自定義日誌框架,定製化顯示日誌樣式,定製化配置是否顯示日誌等,可參考:android日誌框架
-
可以通過配置gradle,讓測試環境中顯示日誌資訊,在正式環境中不顯示日誌資訊;
-
android studio提供了斷點除錯功能,包含了求值除錯,條件斷點,日誌斷點,方法斷點,異常斷點等等;