使用Timber來幫忙打印log

廖時賢
Nov 20, 2020

--

之前有次在開發專案的時候,忘記是加入了哪個Library,在使用Log來除錯的時候突然跳出了這個警告訊息

Using 'Log' instead of 'Timber'

因為沒看過這個訊息就想說研究一下Timber到底是甚麼,也因此發現了這個實用的小工具,對於Android開發者在除錯上可以簡化一些繁瑣的步驟,現在就來介紹它!!

簡介

Timber是由Android大神Jake Wharton所製作,這個小巧的Library原本是J神自己手動加到每個他做的小專案中,後來可能是因為受不了每個專案都要複製貼上一次,J神就把這個class(沒錯,就只是一個class而已!!夠小了吧😂)製作成Library開源出來造福群眾了!雖然說只是一個class,不過其中包含的功能可不少,接著就一一介紹他的使用情境及便利處。

使用方法

首先把Timber加入Dependencies中

implementation 'com.jakewharton.timber:timber:4.7.1'

接著在application的onCreate()中加入 Timber.Tree的實體,可以自訂Tree或者使用預設的DebugTree,這邊先以DebugTree做例子

種樹囉~~

接著就可以在APP中的任何地方,呼叫Timber的靜態方法來打印Log囉~

只在Debug環境下打印Log

Google建議打印Log的動作只在Debug模式下進行,如果不要每次發布新版本之前把全部的Log移除掉,可以透過BuildConfig中的DEBUG屬性來判斷是否要印Log

這樣做不是不行,只是每次要印Log之前都要再做一次判斷,對於開發者來說是一件無聊又不得不做的事;而透過Timber,只需要在application中做一次判斷,後面呼叫時就會全部幫你做好了~

這樣一來,不用擔心在哪個地方忘了做判斷,進而造成在production版本中還是打印Log,使得APP運作方式可能因此洩漏,也讓在看code時更加的輕鬆不用一直看到重複的環境判斷。

自動以類別名稱做TAG

傳統使用傳統使用android.util.Log時,在每次印Log都需要傳入一個tag來標示這個Log的用途,而通常這個tag是類別名稱,所以可能會在每個類別的companion object中寫一個TAG常數

而使用Timber後這個步驟也不需要了,因為Timber會自動把類別名稱當作tag,所以上面的例子使用Timber後就變成

而印出來的Log會自動包含MainActivity作為tag

如果需要自訂一個Tag怎麼辦?

在開發階段,很常會需要透過Log來做除錯,如果在同一個類別裡面印了太多Log,有時候閱讀起來也不太容易,這時候可以透過設定Tag來幫忙

上面程式碼跑出來的結果是這樣

這篇要特別註明一下,透過Timber.tag()這個方法設定的tag是一次性的,當跑過之後就會變回原本的類別名稱作為tag,可是如果是像我這樣有點強迫症的工程師可能會希望自己的Log印出來整整齊齊的,最好是Tag裡面有類別名稱/方法名稱,後面在印出想印的訊息,比如

[MainActivity][onCreate]: activity created
[MainActivity][onResume]: activity resume

如果想要做成這樣,確實可以透過Timber.tag()在每個方法裡面設定一個tag,不過這樣做效率太低,反而喪失了使用Timber的優勢,所以應該要這樣做-

在森林裡種下自己的樹吧!!!自訂Timber.Tree

標題其實是在看完Timber的原始碼之後就很想下的,只能說J神的命名很有趣(有興趣的可以到Github看看);這個方法是參考這裡稍作格式修改,在Timber中,不管是Tag的產生或者是真的呼叫Logging方法都是在Tree中進行,所以我們可以自訂一個Tree能產生層級式Tag,這樣當打印Log的時候自然就會看到我們想要的Tag了。

首先先定義一個MultiTagTree,繼承Timber原本就有的DebugTree,之後覆寫createStackElementTag()這個方法,這樣一來產生出來的Tag就會是上面那樣[類別名稱][方法名稱],後面接著想印出來的訊息

MultiTagTree.kt
Log結果

透過這個自訂的Tree,印出來的Log包含了更多的訊息,而如果還是有特別情形下需要用自訂的Tag時,就照上一段落一樣呼叫.tag()方法設置,在之後就又會變成包含方法名稱的格式了。

而在StackTraceElement這個類別中,除了可以拿到類別名稱和方法名稱以外,還可以拿到呼叫行數(getLineNumber())以及檔案名稱(getFileName()),所以在上面StackOverflow的連結中,就有其他開發者在下面提到這個方式可以直接點擊到該Log呼叫處,使用上更加方便

LineNumberDebugTree.kt & Log結果

結論

Timber真的是一個小巧精美的Lib,讓開發者們在開發階段可以更輕鬆的印出想要的Log,減少做一些無聊重複卻又不得不做的事情。

說到這邊突然有點感慨,想當初要換跑道到程式開發時家裡人一直告誡要想清楚,因為程式這條路是不歸路,必須時時更新自己的資訊才不會被時代淘汰;雖然說這是事實,但同時我卻又很慶興是在這個時間點才換,因為在前人奠定的基礎上,很多事情變得相對來得輕鬆很多,完全就是前人種樹後人乘涼啊;也因此雖然目前還算是個小菜鳥,但希望寫出來的文章可以幫助到想要換跑道或者剛要起步的開發者,讓大家開發路上可以走得更順暢一點。

參考資料

Timber Repository
Better Logging In Android Using Timber
Log method name and line number in Timber

--

--

廖時賢

Android/React Native developer. Start coding by interesting and become a job now.