Android KLog源代码分析

  • Android KLog源代码分析

    • 代码结构
    • 详细分析
      • BaseLog
      • FileLog
      • JsonLog
      • XmlLog
    • 核心文件KLogjava分析
    • 遇到的问题

一直使用这个库。但没有细致研究。今天就来研究一下。该库的地址:

KLog,在这里先感谢下作者。棒棒哒!

代码结构

整个代码的结构非常easy。例如以下:

libraryklogBaseLog.javaFileLog.javaJsonLog.javaXmlLog.javaKLog.javaKLogUtil.java

共六个文件:

  • BaseLog.java,支持主要的log打印
  • FileLog.java。支持以文件的形式保存log
  • JsonLog.java,支持打印json对象和json数组
  • XmlLog.java,支持打印Xml形式的log

详细分析

BaseLog

两个方法:

public class BaseLog {private static final int MAX_LENGTH = 4000;public static void printDefault(int type, String tag, String msg) {int index = 0;int length = msg.length();int countOfSub = length / MAX_LENGTH;if (countOfSub > 0) {// 超过指定长度,粉刺打印。这样就避免了系统默认的log长度限制了for (int i = 0; i < countOfSub; i++) {String sub = msg.substring(index, index + MAX_LENGTH);printSub(type, tag, sub);index += MAX_LENGTH;}printSub(type, tag, msg.substring(index, length));// 打印余数部分} else {printSub(type, tag, msg);}}private static void printSub(int type, String tag, String sub) {switch (type) {case KLog.V:Log.v(tag, sub);break;case KLog.D:Log.d(tag, sub);break;case KLog.I:Log.i(tag, sub);break;case KLog.W:Log.w(tag, sub);break;case KLog.E:Log.e(tag, sub);break;case KLog.A:Log.wtf(tag, sub);break;}}}

这里突破了android系统的log字数限制,事实上就是超过字数限制后。採用分次打印的方法来打印,其它代码不做分析,比較简单。

FileLog

三个方法

public class FileLog {private static final String FILE_PREFIX = "KLog_";private static final String FILE_FORMAT = ".log";/*** @param tag             log tag* @param targetDirectory log file save dir* @param fileName        log file name* @param headString      log file 文件头* @param msg             log file log内容主体*/public static void printFile(String tag, File targetDirectory, @Nullable String fileName, String headString, String msg) {fileName = (fileName == null) ? getFileName() : fileName;if (save(targetDirectory, fileName, msg)) {Log.d(tag, headString + " save log success ! location is >>>" + targetDirectory.getAbsolutePath() + "/" + fileName);} else {Log.e(tag, headString + "save log fails !");}}/*** @param dic      log file save dir* @param fileName og file name* @param msg      log file log内容主体* @return true if save success*/private static boolean save(File dic, @NonNull String fileName, String msg) {File file = new File(dic, fileName);try {OutputStream outputStream = new FileOutputStream(file);OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8");outputStreamWriter.write(msg);outputStreamWriter.flush();outputStream.close();return true;} catch (FileNotFoundException e) {e.printStackTrace();return false;} catch (UnsupportedEncodingException e) {e.printStackTrace();return false;} catch (IOException e) {e.printStackTrace();return false;} catch (Exception e) {e.printStackTrace();return false;}}/*** 当未设置文件名称时,随机生成一个文件名称** @return default file name*/private static String getFileName() {Random random = new Random();return FILE_PREFIX + Long.toString(System.currentTimeMillis() + random.nextInt(10000)).substring(4) + FILE_FORMAT;}}
JsonLog

JsonLog就更简单了,仅仅有一个方法(本宝宝曾经还以为Json打印会非常麻烦呢)

public class JsonLog {public static void printJson(String tag, String msg, String headString) {String message;try {if (msg.startsWith("{")) {// 处理json对象JSONObject jsonObject = new JSONObject(msg);message = jsonObject.toString(KLog.JSON_INDENT);} else if (msg.startsWith("[")) {// 处理json数组JSONArray jsonArray = new JSONArray(msg);message = jsonArray.toString(KLog.JSON_INDENT);} else {message = msg;}} catch (JSONException e) {message = msg;}KLogUtil.printLine(tag, true);// 调用格式化方法message = headString + KLog.LINE_SEPARATOR + message;String[] lines = message.split(KLog.LINE_SEPARATOR);for (String line : lines) {Log.d(tag, "║ " + line);}KLogUtil.printLine(tag, false);// 调用格式化方法}
}
XmlLog

两个方法:

public class XmlLog {/*** 打印xml** @param tag        log tag* @param xml        xml content* @param headString 文件头*/public static void printXml(String tag, String xml, String headString) {if (xml != null) {xml = XmlLog.formatXML(xml);xml = headString + "\n" + xml;} else {xml = headString + KLog.NULL_TIPS;}KLogUtil.printLine(tag, true);String[] lines = xml.split(KLog.LINE_SEPARATOR);for (String line : lines) {if (!KLogUtil.isEmpty(line)) {Log.d(tag, "║ " + line);}}KLogUtil.printLine(tag, false);}/*** @param inputXML xml content* @return 格式化后的xml String*/private static String formatXML(String inputXML) {try {Source xmlInput = new StreamSource(new StringReader(inputXML));StreamResult xmlOutput = new StreamResult(new StringWriter());Transformer transformer = TransformerFactory.newInstance().newTransformer();transformer.setOutputProperty(OutputKeys.INDENT, "yes");transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");transformer.transform(xmlInput, xmlOutput);return xmlOutput.getWriter().toString().replaceFirst(">", ">\n");} catch (Exception e) {e.printStackTrace();return inputXML;}}}

细心的你会发现。不管是Json形式还是XML形式。调用的都是系统原生的方法来处理数据,因此又时候对熟悉熟悉java(或android)提供的方法还是非常方便的。哈哈。

上面用到的KLogUtil,例如以下:

public class KLogUtil {public static boolean isEmpty(String line) {return TextUtils.isEmpty(line) || line.equals("\n") || line.equals("\t") || TextUtils.isEmpty(line.trim());}public static void printLine(String tag, boolean isTop) {if (isTop) {Log.d(tag, "╔═══════════════════════════════════════════════════════════════════════════════════════");} else {Log.d(tag, "╚═══════════════════════════════════════════════════════════════════════════════════════");}}}

核心文件KLog.java分析

给方法主要提供了相似于系统log方法的不同重载,比較简单,我这里要讲的是那个获取log详细有关的类名、方法名、行号等。与之相关的就是wrapperContent这种方法了。

private static String[] wrapperContent(int stackTraceIndex, String tagStr, Object... objects) {StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();StackTraceElement targetElement = stackTrace[stackTraceIndex];String className = targetElement.getClassName();// 得到类名String[] classNameInfo = className.split("\\.");// 第一种形式if (classNameInfo.length > 0) {className = classNameInfo[classNameInfo.length - 1] + SUFFIX;}if (className.contains("$")) {//另外一种形式className = className.split("\\$")[0] + SUFFIX;}String methodName = targetElement.getMethodName();//得到方法名int lineNumber = targetElement.getLineNumber();//得到所在的行号if (lineNumber < 0) {lineNumber = 0;}String tag = (tagStr == null ? className : tagStr);if (mIsGlobalTagEmpty && TextUtils.isEmpty(tag)) {tag = TAG_DEFAULT;} else if (!mIsGlobalTagEmpty) {tag = mGlobalTag;}// 得到消息主体String msg = (objects == null) ? NULL_TIPS : getObjectsString(objects);String headString = "[ (" + className + ":" + lineNumber + ")#" + methodName + " ] ";return new String[]{tag, msg, headString};}/*** 得到消息主体** @param objects 消息对象数组* @return 消息主体字符串*/private static String getObjectsString(Object... objects) {if (objects.length > 1) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("\n");for (int i = 0; i < objects.length; i++) {Object object = objects[i];if (object == null) {stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(NULL).append("\n");} else {stringBuilder.append(PARAM).append("[").append(i).append("]").append(" = ").append(object.toString()).append("\n");}}return stringBuilder.toString();} else {Object object = objects[0];return object == null ?

NULL : object.toString(); } }

分析完成,是不是非常easy,假设你看了这个库的代码。你会认为我的分析都是多余的。

遇到的问题

在使用KLog打印json形式信息时。假设网络请求时异步的,会导致KLog.json打印的格式出现错乱。即一个结果还没有全然打印出来。里外一个就開始打印了,这个应该是并发导致的问题,之后我会在KLog的基础上对这个问题进行优化的。

转载于:https://www.cnblogs.com/claireyuancy/p/7380903.html

Android KLog源代码分析相关推荐

  1. android settings源代码分析(2)

    通过前一篇文章  Android settings源代码分析(1)  分析,大概知道了Settings主页面是如何显示,今天主要分析"应用"这一块google是如何实现的. 应用对 ...

  2. Android 消息处理源代码分析(1)

    Android 消息处理源代码分析(1) 在Android中,通常被使用的消息队列的代码在文件夹\sources\android-22\android\os下,涉及到下面几个类文件 Handler.j ...

  3. android settings源代码分析(3)

    本章主要分析google settings里面存储模块的代码. 存储模块所在的fragment为: [html] view plaincopy <!-- Storage --> <h ...

  4. Github android客户端源代码分析之一:环境搭建

    1.下载相应的包及项目,参考https://github.com/github/android/wiki/Building-From-Eclipse. 2.若需查看某些包的源文件或者javadoc,则 ...

  5. Android深入源代码分析理解Aidl总体调用流程(雷惊风)

    2017年開始上班的第一天.老不想工作了,假期感觉还没開始就已经结束了,唉,时间就是这样,新的一年開始了,尽管非常不想干正事,没办法,必须干起来.由于后边的路还非常长,距离六十岁还非常远. 刚上班也没 ...

  6. android map有序存储,Android ArrayMap源代码分析

    分析源码之前先来介绍一下ArrayMap的存储结构,ArrayMap数据的存储不同于HashMap和SparseArray. Java提供了HashMap,但是HashMap对于手机端而言,对空间的利 ...

  7. android settings源代码分析(1)

    1.Android settings源码的source code路径为: kikat_4.4_CTS\packages\apps\Settings 2.settings主界面UI布局 Settings ...

  8. android stk 源代码分析,Android源码分析--STK

    文件:StkAppService.java 函数:onCreate() STK的APP程序启动后执行的第一个函数,会调用方法: com.android.internal.telephony.gsm.s ...

  9. [Android]Volley源代码分析(店)应用

    通过前面的谈话,我相信你有Volley有了一定的了解了原理.本章将给出一些我们的应用程序都可以在样品中直接使用,第一样品是 NetworkImageView类,事实上NetworkImageView顾 ...

  10. android scrcpy 源代码分析,Scrcpy投屏原理浅析-设备控制篇

    起初我真的想过自己单独写一套来着,后来发现 Scrcpy与vysor是都是投屏中比较优秀的项目了,非侵入性,不需要设备单独 scrcpy启动阶段 它到底是怎么做到执行scrcpy命令,在较短的时间内就 ...

最新文章

  1. 客快物流大数据项目(五十三):实时ETL模块开发准备
  2. stylecloud.gen_stylecloud() 参数详解
  3. 新生代农民工必看:模拟器eNSP安装教程(附下载链接)
  4. [HNOI2016] 大数(莫队)
  5. android model 设计,Android model层设计
  6. 阿里P8架构师谈:分布式系统全局唯一ID简介、特点、5种生成方式
  7. python可以处理的文件类型_Python学习笔记之数据类型与文件处理
  8. 图解TCPIP-IP 网际协议-IP包
  9. Vue 中是如何解析 template 字符串为 VNode 的?
  10. py樱花代码_武汉大学生用代码敲出樱花绽放,这个开源项目也很酷炫
  11. jersey restful 测试_Jersey 开发RESTful(七)Jersey快速入门
  12. layui.table(表格)跨页多选
  13. 分布式IO模块ET 200SP基座单元( BaseUnit)使用方法
  14. mac 安装 Adobe CC XD
  15. html表单验证方法,简述HTML交互式表单验证方法
  16. html5显示状态灯,如何使用css3+html5来制作文字霓虹灯效果
  17. ChatGPT4 的体验 一站式 AI工具箱 -—Poe(使用教程)
  18. 集体备课模板_集体备课模板
  19. Mac 关闭双空格插入句号、自动大写首字母、拼写纠正
  20. 模块:time(时间)

热门文章

  1. 2008年入职华为,开始运维生涯
  2. 运维专家写给运维工程师的 6 条人生忠告
  3. DevOps:让开发和运维告别“相爱相杀”
  4. 好开心,明天就上班了
  5. 时隔两年,运维人必备的PuTTY 终于发布新版!
  6. IT人喝酒不同岗位不同姿态,最服运维!
  7. IT江湖,哪个门派最挨踢?
  8. 这才是真正的薪资水平
  9. 圆满结束,一睹各位大神风采
  10. Vue笔记:使用 axios 中 this 指向问题