课程名称:移动端架构师
课程章节:HiLog库架构设计与开发
课程讲师:CrazyCodeBoy LovelyChubby
课程内容:
架构易用高扩展的日志组件HiLog
日志组件是一款中大型APP所不可或缺的一部分,好的一款日志组件不仅能够起到收集日志的作用,更能够实现日志操作的多样化。
例如:日志的保存,日志的可视化,对象打印,日志的在线收集,线上问题定位的辅助
HiLog库疑难点分析与架构设计
需求分析
能够打印对照信息
支持任何数据类型的打印
支持实现日志可视化
能够实现文件打印模块
支持不同打印器的插拔
日志经历的几个过程
技术点分析
日志收集 | 日志加工 | 日志打印 |
---|---|---|
面向接口编程 | 堆栈信息相关技术 | 文件IO技术(文件打印) |
设计模式 | 序列化 | 多线程技术(线程复用、线程同步) |
解耦设计 | 日志格式化 | UI以及列表相关技术 |
疑难点分析
堆栈信息获取
打印器插拔设计
线程复用防止频繁的创建线程
线程同步
架构设计
HiLogFormatter.java
org.devio.hi.library.logHiLogFormatter<> { String (data)}
HiStackTraceFormatter.java
org.devio.hi.library.logHiStackTraceFormatter HiLogFormatter<StackTraceElement[]> { String (StackTraceElement[] stackTrace) { StringBuilder sb = StringBuilder()(stackTrace == || stackTrace.== ) { } (stackTrace.== ) { + stackTrace[].toString()} { (i = len = stackTrace.i < leni++) { (i == ) { sb.append()} (i != len - ) { sb.append()sb.append(stackTrace[i].toString())sb.append()} { sb.append()sb.append(stackTrace[i].toString())} } sb.toString()} } }
HiThreadFormatter.java
org.devio.hi.library.logHiThreadFormatter HiLogFormatter<Thread> { String (Thread data) { + data.getName()} }
HiLogPrinter.java
org.devio.hi.library.logandroidx.annotation.HiLogPrinter { (HiLogConfig configlevelString tagString printString)}
HiConsolePrinter.java
org.devio.hi.library.logandroid.util.Logandroidx.annotation.org.devio.hi.library.log.HiLogConfig.HiConsolePrinter HiLogPrinter { (HiLogConfig configlevelString tagString printString) { len = printString.length()countOfSub = len / (countOfSub > ) {index = (i = i < countOfSubi++) {Log.(leveltagprintString.substring(indexindex + ))index += } (index != len) {Log.(leveltagprintString.substring(indexlen))}} { Log.(leveltagprintString)} } }
HiFilePrinter.java
org.devio.hi.library.logandroidx.annotation.java.io.BufferedWriterjava.io.Filejava.io.FileWriterjava.io.IOExceptionjava.text.SimpleDateFormatjava.util.Datejava.util.Localejava.util.TimeZonejava.util.concurrent.BlockingQueuejava.util.concurrent.ExecutorServicejava.util.concurrent.Executorsjava.util.concurrent.LinkedBlockingQueueHiFilePrinter HiLogPrinter { ExecutorService = Executors.()String LogWriter PrintWorker HiFilePrinter HiFilePrinter (String logPathretentionTime) { (== ) { = HiFilePrinter(logPathretentionTime)} } (String logPathretentionTime) { .= logPath.= retentionTime.= LogWriter().= PrintWorker()cleanExpiredLog()} (HiLogConfig configlevelString tagString printString) { timeMillis = System.()(!.isRunning()) { .start()} .put(HiLogMo(timeMillisleveltagprintString))} (HiLogMo logMo) { String lastFileName = .getPreFileName()(lastFileName == ) { String newFileName = genFileName()(.isReady()) { .close()} (!.ready(newFileName)) { } } .append(logMo.flattenedLog())} String () { SimpleDateFormat sdf = SimpleDateFormat(Locale.)sdf.setTimeZone(TimeZone.())sdf.format(Date(System.()))} () { (<= ) { } currentTimeMillis = System.()File logDir = File()File[] files = logDir.listFiles()(files == ) { } (File file : files) { (currentTimeMillis - file.lastModified() > ) { file.delete()} } } PrintWorker Runnable { BlockingQueue<HiLogMo> = LinkedBlockingQueue<>()(HiLogMo log) { { .put(log)} (InterruptedException e) { e.printStackTrace()} } () { () { } } () { () { .execute()= } } () { HiLogMo log{ () { log = .take()doPrint(log)} } (InterruptedException e) { e.printStackTrace()() { = } } } } LogWriter { String File BufferedWriter () { != } String () { } (String newFileName) { = newFileName= File(newFileName)(!.exists()) { { File parent = .getParentFile()(!parent.exists()) { parent.mkdirs()} .createNewFile()} (IOException e) { e.printStackTrace()= = } } { = BufferedWriter(FileWriter())} (Exception e) { e.printStackTrace()= = } } () { (!= ) { { .close()} (IOException e) { e.printStackTrace()} { = = = } } } (String flattenedLog) { { .write(flattenedLog).newLine().flush()} (IOException e) { e.printStackTrace()} } } }
HiViewPrinter.java
org.devio.hi.library.logandroid.app.Activityandroid.view.LayoutInflaterandroid.view.Viewandroid.view.ViewGroupandroid.widget.FrameLayoutandroid.widget.TextViewandroidx.annotation.androidx.recyclerview.widget.LinearLayoutManagerandroidx.recyclerview.widget.RecyclerVieworg.devio.hi.library.Rjava.util.ArrayListjava.util.ListHiViewPrinter HiLogPrinter { RecyclerView LogAdapter HiViewPrinterProvider (Activity activity) { FrameLayout rootView = activity.findViewById(android.R.id.)= RecyclerView(activity)= LogAdapter(LayoutInflater.(.getContext()))LinearLayoutManager layoutManager = LinearLayoutManager(.getContext()).setLayoutManager(layoutManager).setAdapter()= HiViewPrinterProvider(rootView)} HiViewPrinterProvider () { } (HiLogConfig configlevelString tagString printString) { .addItem(HiLogMo(System.()leveltagprintString)).smoothScrollToPosition(.getItemCount() - )} LogAdapter RecyclerView.Adapter<LogViewHolder> { LayoutInflater List<HiLogMo> = ArrayList<>()(LayoutInflater inflater) { .= inflater} (HiLogMo logItem) { .add(logItem)notifyItemInserted(.size() - )} LogViewHolder (ViewGroup parentviewType) { View itemView = .inflate(R.layout.parent)LogViewHolder(itemView)} (LogViewHolder holderposition) { HiLogMo logItem = .get(position)color = getHighlightColor(logItem.)holder..setTextColor(color)holder..setTextColor(color)holder..setText(logItem.getFlattened())holder..setText(logItem.)} (logLevel) { highlight(logLevel) { HiLogType.: highlight = HiLogType.: highlight = HiLogType.: highlight = HiLogType.: highlight = HiLogType.: highlight = : highlight = } highlight} () { .size()} } LogViewHolder RecyclerView.ViewHolder { TextView TextView (View itemView) { (itemView)= itemView.findViewById(R.id.)= itemView.findViewById(R.id.)} } }
HiLogConfig.java
org.devio.hi.library.logHiLogConfig { = HiThreadFormatter = HiThreadFormatter()HiStackTraceFormatter = HiStackTraceFormatter()JsonParser () { } String () { } () { } () { } () { } HiLogPrinter[] () { } JsonParser { String (Object src)} }
HiLog.java
org.devio.hi.library.logandroidx.annotation.java.util.Arraysjava.util.ListHiLog { String { String className = HiLog..getName()= className.substring(className.lastIndexOf() + )} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (Object... contents) { (HiLogType.contents)} (String tagObject... contents) { (HiLogType.tagcontents)} (typeObject... contents) { (typeHiLogManager.().getConfig().getGlobalTag()contents)} (typeString tagObject... contents) { (HiLogManager.().getConfig()typetagcontents)} (HiLogConfig configtypeString tagObject... contents) { (!config.enable()) { } StringBuilder sb = StringBuilder()(config.includeThread()) { String threadInfo = HiLogConfig..format(Thread.())sb.append(threadInfo).append()} (config.stackTraceDepth() > ) { String stackTrace = HiLogConfig..format( HiStackTraceUtil.(Throwable().getStackTrace()config.stackTraceDepth()))sb.append(stackTrace).append()} String body = (contentsconfig)(body != ) {body = body.replace()} sb.append(body)List<HiLogPrinter> printers = config.printers() != ? Arrays.(config.printers()) : HiLogManager.().getPrinters()(printers == ) { } (HiLogPrinter printer : printers) { printer.print(configtypetagsb.toString())} } String (Object[] contentsHiLogConfig config) { (config.injectJsonParser() != ) { (contents.== && contents[] String) { (String) contents[]} config.injectJsonParser().toJson(contents)} StringBuilder sb = StringBuilder()(Object o : contents) { sb.append(o.toString()).append()} (sb.length() > ) { sb.deleteCharAt(sb.length() - )} sb.toString()} }
HiLogManager.java
org.devio.hi.library.logandroidx.annotation.java.util.ArrayListjava.util.Arraysjava.util.ListHiLogManager { HiLogConfig HiLogManager List<HiLogPrinter> = ArrayList<>()(HiLogConfig configHiLogPrinter[] printers) { .= config..addAll(Arrays.(printers))} HiLogManager () { } (HiLogConfig configHiLogPrinter... printers) { = HiLogManager(configprinters)} HiLogConfig () { } List<HiLogPrinter> () { } (HiLogPrinter printer) { .add(printer)} (HiLogPrinter printer) { (!= ) { .remove(printer)} } }
HiLogType.java
org.devio.hi.library.logandroid.util.Logandroidx.annotation.java.lang.annotation.java.lang.annotation.RetentionPolicyHiLogType { ({}) (RetentionPolicy.) @{ } = Log.= Log.= Log.= Log.= Log.= Log.}
HiStackTraceUtil.java
org.devio.hi.library.logHiStackTraceUtil { StackTraceElement[] (StackTraceElement[] stackTraceString ignorePackagemaxDepth) { ((stackTraceignorePackage)maxDepth)} StackTraceElement[] (StackTraceElement[] stackTraceString ignorePackage) { ignoreDepth = allDepth = stackTrace.String className(i = allDepth - i >= i--) { className = stackTrace[i].getClassName()(ignorePackage != && className.startsWith(ignorePackage)) { ignoreDepth = i + } } realDepth = allDepth - ignoreDepthStackTraceElement[] realStack = StackTraceElement[realDepth]System.(stackTraceignoreDepthrealStackrealDepth)realStack} StackTraceElement[] (StackTraceElement[] callStackmaxDepth) { realDepth = callStack.(maxDepth > ) { realDepth = Math.(maxDepthrealDepth)} StackTraceElement[] realStack = StackTraceElement[realDepth]System.(callStackrealStackrealDepth)realStack} }
HiViewPrinterProvider.java
org.devio.hi.library.logandroid.graphics.Colorandroid.view.Gravityandroid.view.Viewandroid.view.ViewGroupandroid.widget.FrameLayoutandroid.widget.TextViewandroidx.recyclerview.widget.RecyclerVieworg.devio.hi.library.util.HiDisplayUtilHiViewPrinterProvider { FrameLayout View FrameLayout RecyclerView (FrameLayout rootViewRecyclerView recyclerView) { .= rootView.= recyclerView} String = String = () { (.findViewWithTag() != ) { } FrameLayout.LayoutParams params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.ViewGroup.LayoutParams.)params.= Gravity.| Gravity.View floatingView = genFloatingView()floatingView.setTag()floatingView.setBackgroundColor(Color.)floatingView.setAlpha()params.= HiDisplayUtil.(.getResources()).addView(genFloatingView()params)} () { (.findViewWithTag() != ) { } FrameLayout.LayoutParams params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.HiDisplayUtil.(.getResources()))params.= Gravity.View logView = genLogView()logView.setTag().addView(genLogView()params)= } () { = .removeView(genLogView())} () { .removeView(genFloatingView())} View () { (!= ) { } TextView textView = TextView(.getContext())textView.setOnClickListener(View.OnClickListener() { (View v) { (!) { showLogView()} } })textView.setText()= textView} View () { (!= ) { } FrameLayout logView = FrameLayout(.getContext())logView.setBackgroundColor(Color.)logView.addView()FrameLayout.LayoutParams params = FrameLayout.LayoutParams(ViewGroup.LayoutParams.ViewGroup.LayoutParams.)params.= Gravity.TextView closeView = TextView(.getContext())closeView.setOnClickListener(View.OnClickListener() { (View v) { closeLogView()} })closeView.setText()logView.addView(closeViewparams).= logView} }
HiLogMo.java
org.devio.hi.library.logjava.text.SimpleDateFormatjava.util.LocaleHiLogMo { SimpleDateFormat = SimpleDateFormat(Locale.)String String (timeMillislevelString tagString log) { .= timeMillis.= level.= tag.= log} String () { getFlattened() + + } String () { format() + + + + + } String (timeMillis) { .format(timeMillis)} }
HiLog日志框架的初始化
MApplication : Application() { () { .onCreate() HiLogManager.init( : HiLogConfig() { (): JsonParser? { JsonParser src JSONObject.toJSONString(src) } (): String { } (): Boolean { } (): Boolean { } (): Int { } }HiConsolePrinter()HiFilePrinter.getInstance(..) ) } }
HiLog日志框架的使用
HiLog.d("hilog")
课程收获:
谢谢老师,讲的非常细致,很容易懂,期待后边的学习