成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

安卓to鴻蒙系列:Timber

系統
文章由鴻蒙社區產出,想要了解更多內容請前往:51CTO和華為官方戰略合作共建的鴻蒙技術社區https://harmonyos.51cto.com

[[395653]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

目錄

  • Guide
  • 原理
  • 知識點
  • 移植到鴻蒙

Guide

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

大神JakeWharton的Timber是我寫日志的最愛,幾乎在所有的項目中都用。當然一般我會通過Timber使用Logger,原因很簡單,因為Timber接口簡潔,Logger的輸出樣式好看。常規套路:

  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. }); 

當然它的內部實現也一樣完美。咱們往下看。

原理

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

比如樹A表示輸出日志到控制臺,樹B表示輸出日志到文件,樹C輸出到網絡。

代碼實現上,Timber使用了外觀(facade)模式。

  • Tree類是外觀類,通過plant方法Timber持有Tree類的實例,Timber中的asTree、tag方法將它暴露出去,而對于調用者來說依賴的是抽象類Tree,而不是具體的Tree的實現,如果要更換或者添加Tree類實例,只需要調用plant等相關方法即可,所有調用者使用Tree對象的地方不需要做任何修改,這是符合面向對象依賴倒置原則的一個很好的體現。

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

更詳細的分析請移步

  1. Timber 源碼解析
  2. Timber源碼解析及涉及知識點總結

知識點

1.臨時tag的實現方法

  • 很簡單,Timber.tag("臨時tag").d(xxx);設置臨時tag。使用一次就刪除。
  • 為了性能,使用ThreadLocal 以空間換時間。
  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的使用,因為FOREST為單例,所以對其讀寫要加鎖。

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

4.關于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 轉成Tree[]數組?

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

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

不推薦使用 toArray() 無參方法,此方法返回值只能是Object[]類,若強轉將出現ClassCastException錯誤。

移植到鴻蒙

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

HiLog在tag的基礎上擴展了HiLogLabel的概念。

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

如果每次都new一個label,太低效,所以這里可以優化。比如如果和上次一樣,就使用上次的。或者使用對象池技術。

關鍵代碼:

  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.   } 

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2021-04-27 09:22:28

鴻蒙HarmonyOS應用

2021-05-11 14:43:16

鴻蒙HarmonyOS應用

2021-07-26 10:09:43

鴻蒙HarmonyOS應用

2019-06-20 16:07:12

鴻蒙安卓操作系統

2020-09-10 09:30:03

鴻蒙安卓操作系統

2013-11-04 14:49:34

安卓

2018-02-09 08:59:47

安卓FuchsiaiOS

2019-07-12 16:00:25

華為禁令開發

2021-06-04 05:13:22

鴻蒙

2021-05-18 15:44:13

IOS安卓鴻蒙

2021-07-06 18:21:31

鴻蒙HarmonyOS應用

2013-04-24 11:33:50

安卓

2013-10-17 10:17:41

安卓

2014-12-09 11:15:06

郵箱安卓移動端

2021-02-25 10:40:00

數據

2020-09-29 13:03:45

安卓應用開發工具開發

2011-10-18 13:33:02

思亞諾CMMBDTV

2019-06-11 13:41:45

華為鴻蒙操作系統

2022-07-28 12:06:46

HarmonyOS華為

2024-01-31 17:52:04

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 老头搡老女人毛片视频在线看 | 国产女人与拘做受视频 | 亚洲精品乱码 | 草草在线观看 | 一区二区三区视频在线免费观看 | 日本a视频 | 午夜视频一区 | 国产精品国产精品 | 免费黄网站在线观看 | 日韩精品免费视频 | 在线免费观看成人 | 日韩欧美三区 | 亚洲中午字幕 | 中文字幕精品一区久久久久 | 久久中文视频 | 久久亚洲精品视频 | 99精品久久 | 国产精品一区二区福利视频 | 国产中文字幕在线观看 | 日本视频免费 | 综合久久久 | 人人爽人人草 | 欧美一区二区在线 | 天堂国产 | aaa级片 | 中国免费黄色片 | 久久精品一区二区三区四区 | 国产99视频精品免费播放照片 | 天天操天天射天天舔 | 亚洲性人人天天夜夜摸 | 欧美大片黄 | 国产剧情一区二区三区 | 操网站| 亚洲精品一区国产精品 | 欧美极品视频在线观看 | 午夜影院在线观看 | 色悠悠久 | 天天干天天干 | 久久精品欧美电影 | 国产成人在线一区二区 | 免费一区 |