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

安卓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問(wèn):

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

https://harmonyos.51cto.com

目錄

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

Guide

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

大神JakeWharton的Timber是我寫(xiě)日志的最愛(ài),幾乎在所有的項(xiàng)目中都用。當(dāng)然一般我會(huì)通過(guò)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)即種樹(shù)。每種一棵樹(shù),就擁有一種日志能力。

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

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

  • Tree類是外觀類,通過(guò)plant方法Timber持有Tree類的實(shí)例,Timber中的asTree、tag方法將它暴露出去,而對(duì)于調(diào)用者來(lái)說(shuō)依賴的是抽象類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ì)其讀寫(xiě)要加鎖。

3.static volatile Tree[] forestAsArray ,volatile 保證了可見(jiàn)性

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

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

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

移植到鴻蒙

如果Timber沒(méi)有默認(rèn)提供DebugTree,直接拿來(lái)就能在鴻蒙上使用。DebugTree這棵樹(shù)的能力是在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問(wèn):

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

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來(lái)源: 鴻蒙社區(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)

2013-11-04 14:49:34

安卓

2018-02-09 08:59:47

安卓FuchsiaiOS

2019-07-12 16:00:25

華為禁令開(kāi)發(fā)

2021-05-18 15:44:13

IOS安卓鴻蒙

2021-06-04 05:13:22

鴻蒙

2021-07-06 18:21:31

鴻蒙HarmonyOS應(yīng)用

2013-10-17 10:17:41

安卓

2014-12-09 11:15:06

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

2013-04-24 11:33:50

安卓

2011-10-18 13:33:02

思亞諾CMMBDTV

2021-02-25 10:40:00

數(shù)據(jù)

2020-09-29 13:03:45

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

2019-06-11 13:41:45

華為鴻蒙操作系統(tǒng)

2024-01-31 17:52:04

2022-07-28 12:06:46

HarmonyOS華為
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 手机看片在线播放 | 免费三级黄 | 黄色成人免费看 | 99国产精品久久久 | 一二三在线视频 | 亚洲第一福利视频 | 国产激情 | 范冰冰一级做a爰片久久毛片 | 日韩欧美大片在线观看 | 国产精品久久久久久久久污网站 | 国产精品一区三区 | 国产农村妇女精品一二区 | 国产精品色 | 美女天天干天天操 | 蜜月va乱码一区二区三区 | 精品国产乱码久久久久久牛牛 | 91大片| 免费看的av | 亚洲视频在线看 | 91视频网| 久久午夜剧场 | 亚洲综合视频 | 日韩一区和二区 | 亚洲精品在线视频 | 欧美成人精品一区二区三区 | 久久色视频 | 国久久 | 视频一区 亚洲 | 国产精品久久久久久久久久 | 久久久91精品国产一区二区三区 | 日韩视频在线免费观看 | 黄 色 毛片免费 | 波多野吉衣在线播放 | 99热这里有精品 | 精品96久久久久久中文字幕无 | 精品国产一区二区三区久久影院 | 国产女人与拘做受免费视频 | 日韩欧美在线不卡 | 欧美亚洲视频 | 美女高潮网站 | 精品欧美一区二区中文字幕视频 |