自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

安卓to鴻蒙系列:Timber

系統(tǒng)
文章由鴻蒙社區(qū)產(chǎn)出,想要了解更多內(nèi)容請(qǐng)前往:51CTO和華為官方戰(zhàn)略合作共建的鴻蒙技術(shù)社區(qū)https://harmonyos.51cto.com

[[395653]]

想了解更多內(nèi)容,請(qǐng)?jiān)L問:

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

目錄

  • Guide
  • 原理
  • 知識(shí)點(diǎn)
  • 移植到鴻蒙

Guide

本文基于https://gitee.com/andych008/timber_ohos 分析Timber的源碼,及移植到鴻蒙需要做的工作。

大神JakeWharton的Timber是我寫日志的最愛,幾乎在所有的項(xiàng)目中都用。當(dāng)然一般我會(huì)通過Timber使用Logger,原因很簡(jiǎn)單,因?yàn)門imber接口簡(jiǎn)潔,Logger的輸出樣式好看。常規(guī)套路:

  1. FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 
  2.         .tag("DwGG")   // (Optional) Global tag for every log. Default PRETTY_LOGGER 
  3.         .build(); 
  4.  
  5. Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); 
  6. Timber.plant(new Timber.DebugTree() { 
  7.     @Override 
  8.     protected void log(int priority, String tag, String message, Throwable t) { 
  9.         Logger.log(priority, tag, message, t); 
  10.     } 
  11. }); 

當(dāng)然它的內(nèi)部實(shí)現(xiàn)也一樣完美。咱們往下看。

原理

Timber英文翻譯為**“木材”**。靜態(tài)方法Timber.plant(Tree tree)即種樹。每種一棵樹,就擁有一種日志能力。

比如樹A表示輸出日志到控制臺(tái),樹B表示輸出日志到文件,樹C輸出到網(wǎng)絡(luò)。

代碼實(shí)現(xiàn)上,Timber使用了外觀(facade)模式。

  • Tree類是外觀類,通過plant方法Timber持有Tree類的實(shí)例,Timber中的asTree、tag方法將它暴露出去,而對(duì)于調(diào)用者來說依賴的是抽象類Tree,而不是具體的Tree的實(shí)現(xiàn),如果要更換或者添加Tree類實(shí)例,只需要調(diào)用plant等相關(guān)方法即可,所有調(diào)用者使用Tree對(duì)象的地方不需要做任何修改,這是符合面向?qū)ο笠蕾嚨怪迷瓌t的一個(gè)很好的體現(xiàn)。

另外也使用了委托(delegate)模式。Tree TREE_OF_SOULS把所有的操作都委托給forestAsArray。

更詳細(xì)的分析請(qǐng)移步

  1. Timber 源碼解析
  2. Timber源碼解析及涉及知識(shí)點(diǎn)總結(jié)

知識(shí)點(diǎn)

1.臨時(shí)tag的實(shí)現(xiàn)方法

  • 很簡(jiǎn)單,Timber.tag("臨時(shí)tag").d(xxx);設(shè)置臨時(shí)tag。使用一次就刪除。
  • 為了性能,使用ThreadLocal 以空間換時(shí)間。
  1. public static abstract class Tree { 
  2. final ThreadLocal<String> explicitTag = new ThreadLocal<>(); 
  3.  
  4. String getTag() { 
  5.   String tag = explicitTag.get(); 
  6.   if (tag != null) { 
  7.     explicitTag.remove(); 
  8.   } 
  9.   return tag; 
  1. public static class DebugTree extends Tree { 
  2.  
  3. @Override final String getTag() { 
  4.   String tag = super.getTag(); 
  5.   if (tag != null) { 
  6.     return tag; 
  7.   } 
  8.  
  9.   // DO NOT switch this to Thread.getCurrentThread().getStackTrace(). The test will pass 
  10.   // because Robolectric runs them on the JVM but on Android the elements are different. 
  11.   StackTraceElement[] stackTrace = new Throwable().getStackTrace(); 
  12.   if (stackTrace.length <= CALL_STACK_INDEX) { 
  13.     throw new IllegalStateException( 
  14.         "Synthetic stacktrace didn't have enough elements: are you using proguard?"); 
  15.   } 
  16.   return createStackElementTag(stackTrace[CALL_STACK_INDEX]); 

2.synchronized的使用,因?yàn)镕OREST為單例,所以對(duì)其讀寫要加鎖。

3.static volatile Tree[] forestAsArray ,volatile 保證了可見性

4.關(guān)于plant(Tree tree)方法中的forestAsArray = FOREST.toArray(new Tree[FOREST.size()]);

  1. public static void plant(@NotNull Tree tree) { 
  2.   if (tree == null) { 
  3.     throw new NullPointerException("tree == null"); 
  4.   } 
  5.   if (tree == TREE_OF_SOULS) { 
  6.     throw new IllegalArgumentException("Cannot plant Timber into itself."); 
  7.   } 
  8.   synchronized (FOREST) { 
  9.     FOREST.add(tree); 
  10.     forestAsArray = FOREST.toArray(new Tree[FOREST.size()]); 
  11.   } 
  • 為什么要把List 轉(zhuǎn)成Tree[]數(shù)組?

解釋這個(gè)問題可以參考 深度解析CopyOnWriteArrayList,線程安全的ArrayList!,從使用場(chǎng)景上看,Timber對(duì)于List FOREST讀多寫少,所以只對(duì)寫操作加鎖,讀操作(遍歷時(shí))不需要加鎖。其本質(zhì)上也是讀寫分離的思想,和CopyOnWriteArrayList類似,也是為了性能。

  • 為什么要用List.toArray(T[] a),而不是List.toArray()?

不推薦使用 toArray() 無參方法,此方法返回值只能是Object[]類,若強(qiáng)轉(zhuǎn)將出現(xiàn)ClassCastException錯(cuò)誤。

移植到鴻蒙

如果Timber沒有默認(rèn)提供DebugTree,直接拿來就能在鴻蒙上使用。DebugTree這棵樹的能力是在Logcat中輸出日志。所以移植要做的就是把a(bǔ)ndroid.util.Log換成ohos.hiviewdfx.HiLog。

HiLog在tag的基礎(chǔ)上擴(kuò)展了HiLogLabel的概念。

label = new HiLogLabel(HiLog.DEBUG,0,tag);

如果每次都new一個(gè)label,太低效,所以這里可以優(yōu)化。比如如果和上次一樣,就使用上次的。或者使用對(duì)象池技術(shù)。

關(guān)鍵代碼:

  1. public static class DebugTree extends Tree { 
  2.   private final ThreadLocal<HiLogLabel> currentLabel = new ThreadLocal<>(); 
  3.   private final ThreadLocal<String> currentTag = new ThreadLocal<>(); 
  4.  
  5.  
  6.   @Override protected void log(int priority, String tag, @NotNull String message, Throwable t) { 
  7.     HiLogLabel label = getHiLogLabel(tag); 
  8.  
  9.     if (message.length() < MAX_LOG_LENGTH) { 
  10.       if (priority == HiLog.FATAL) { 
  11.         HiLog.fatal(label,message); 
  12.       } else  if (priority == HiLog.INFO){ 
  13.         HiLog.info(label, message); 
  14.       }else if (priority == HiLog.WARN){ 
  15.         HiLog.warn(label, message); 
  16.       }else if (priority == HiLog.ERROR){ 
  17.         HiLog.error(label, message); 
  18.       }else if (priority == HiLog.DEBUG){ 
  19.         HiLog.debug(label, message); 
  20.       } 
  21.       return
  22.     } 
  23.  
  24.     // Split by line, then ensure each line can fit into Log's maximum length. 
  25.     for (int i = 0, length = message.length(); i < length; i++) { 
  26.       int newline = message.indexOf('\n', i); 
  27.       newline = newline != -1 ? newline : length; 
  28.       do { 
  29.         int end = Math.min(newline, i + MAX_LOG_LENGTH); 
  30.         String part = message.substring(i, end); 
  31.         if (priority == HiLog.FATAL) { 
  32.           HiLog.fatal(label,part); 
  33.         }else  if (priority == HiLog.INFO){ 
  34.           HiLog.info(label, part); 
  35.         }else if (priority == HiLog.WARN){ 
  36.           HiLog.warn(label, part); 
  37.         }else if (priority == HiLog.ERROR){ 
  38.           HiLog.error(label, part); 
  39.         }else if (priority == HiLog.DEBUG){ 
  40.           HiLog.debug(label, part); 
  41.         } 
  42.         i = end
  43.       } while (i < newline); 
  44.     } 
  45.   } 
  46.  
  47.   private HiLogLabel getHiLogLabel(String tag) { 
  48.     HiLogLabel label; 
  49.     if (tag.equals(currentTag.get())) { 
  50.       label = currentLabel.get(); 
  51.     } else { 
  52.       label = new HiLogLabel(HiLog.DEBUG,0,tag); 
  53.       currentLabel.set(label); 
  54.       currentTag.set(tag); 
  55.     } 
  56.     return label; 
  57.   } 

想了解更多內(nèi)容,請(qǐng)?jiān)L問:

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來源: 鴻蒙社區(qū)
相關(guān)推薦

2021-04-27 09:22:28

鴻蒙HarmonyOS應(yīng)用

2021-05-11 14:43:16

鴻蒙HarmonyOS應(yīng)用

2021-07-26 10:09:43

鴻蒙HarmonyOS應(yīng)用

2019-06-20 16:07:12

鴻蒙安卓操作系統(tǒng)

2020-09-10 09:30:03

鴻蒙安卓操作系統(tǒng)

2018-02-09 08:59:47

安卓FuchsiaiOS

2013-11-04 14:49:34

安卓

2021-05-18 15:44:13

IOS安卓鴻蒙

2019-07-12 16:00:25

華為禁令開發(fā)

2021-06-04 05:13:22

鴻蒙

2013-04-24 11:33:50

安卓

2013-10-17 10:17:41

安卓

2014-12-09 11:15:06

郵箱安卓移動(dòng)端

2020-09-29 13:03:45

安卓應(yīng)用開發(fā)工具開發(fā)

2021-02-25 10:40:00

數(shù)據(jù)

2011-10-18 13:33:02

思亞諾CMMBDTV

2021-07-06 18:21:31

鴻蒙HarmonyOS應(yīng)用

2021-10-21 18:57:55

Windows 11操作系統(tǒng)微軟

2020-10-14 07:27:08

MacBook

2013-12-12 16:51:43

安卓進(jìn)化AndroidGoogle
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)