SAF-Kotlin-log 是一个Android的日志框架,这几天我抽空重新更新了一下代码。

github地址:https://github.com/fengzhizi715/SAF-Kotlin-log

一. 打印几个Android常用的对象

1.1 Uri的打印

        Uri uri = Uri.parse("http://www.java2s.com:8080/yourpath/fileName.htm?stove=10&path=32&id=4#harvic");        L.json(uri);

打印效果:


用kotlin打印出漂亮的android日志(三)——基于责任链模式打印任意对象_第1张图片 Uri.png

1.2 Bundle的打印

        User u = new User();        u.userName = "tony";        u.password = "123456";                Bundle bundle = new Bundle();        bundle.putString("key1","this is key1");        bundle.putInt("key2",100);        bundle.putBoolean("key3",true);        bundle.putSerializable("key4",u);        L.json(bundle);

打印效果:


用kotlin打印出漂亮的android日志(三)——基于责任链模式打印任意对象_第2张图片 Bundle.png

目前,它默认支持JSON字符串、集合、Map、Bundle、Intent、Reference、Throwable、Uri等类型的打印,分别做了特别的格式化处理。

二. 使用责任链模式,改造打印对象的方法

在使用责任链模式之前,json()方法是这样的,需要使用when表达式来判断某个类应该对应哪个方法来打印对象。

    /**     * 将任何对象转换成json字符串进行打印     */    @JvmStatic    fun json(obj: Any?) {        if (obj == null) {            d("object is null")            return        }        when(obj) {            is String -> string2JSONString(obj)            is Map<*, *> -> map2JSONString(obj)            is Collection<*> -> collection2JSONString(obj)            is Bundle -> bundle2JSONString(obj)            is Reference<*> -> reference2JSON(obj)            is Intent -> intent2JSON(obj)            is Uri -> uri2JSON(obj)            is Throwable -> throwable2JSONString(obj)            else -> {                try {                    val s = getMethodNames()                    var msg = obj.javaClass.toString() + LoggerPrinter.BR + "║ "                    val objStr = JSON.toJSONString(obj)                    val jsonObject = JSONObject(objStr)                    var message = jsonObject.toString(LoggerPrinter.JSON_INDENT)                    message = message.replace("\n".toRegex(), "\n║ ")                    println(String.format(s, msg+ message))                } catch (e: JSONException) {                    e("Invalid Json")                }            }        }    }

使用责任链模式之后,json()是这样的,一行代码代替了when表达式。

    /**     * 将任何对象转换成json字符串进行打印     */    @JvmStatic    fun json(obj: Any?) {        if (obj == null) {            d("object is null")            return        }        firstHandler.handleObject(obj)    }

2.1 为何需要责任链模式?

目前日志类L只能打印几种类型的对象,或者是默认地将对象打印成json。如果要对某一个对象类做一些个性化的格式化并打印出来,按照原先的做法需要修改json()方法的when表达式。

为了符合“开闭原则”,对扩展开放、对修改关闭。我考虑使用责任链模式来替代when表达式,未来有其他需求只需增加一个单独的Handler即可。

2.2 如何使用责任链模式?

首先,定义一个基类的Handler用于对象的处理,这个Handler还会被赋予一个nextHandler表示责任链中的下一个处理者。如果当前的Handler处理不了,则交给下一个Handler来处理。

/** * Created by tony on 2017/11/27. */abstract class BaseHandler {    // 责任链的下一个节点,即处理者    private var nextHandler: BaseHandler? = null    // 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别    fun handleObject(obj: Any) {        if (obj == null) {            return        }        if (!handle(obj)) {            // 当前处理者不能胜任,则传递至责任链的下一节点            if (this.nextHandler != null) {                this.nextHandler!!.handleObject(obj)            }        }    }    // 设置责任链中的下一个处理者    fun setNextHandler(nextHandler: BaseHandler) {        this.nextHandler = nextHandler    }    // 定义链中每个处理者具体的处理方式    protected abstract fun handle(obj: Any): Boolean}

定义完基类的Handler之后,需要定义各个具体的Handler。以BundleHandler为例,它是专门用于格式化Bundle并打印出来。

import android.os.Bundleimport com.alibaba.fastjson.JSONimport com.safframework.log.Limport com.safframework.log.LoggerPrinterimport com.safframework.log.parser.Parserimport com.safframework.log.utils.Utilsimport org.json.JSONExceptionimport org.json.JSONObject/** * Created by tony on 2017/11/27. */class BundleHandler():BaseHandler(), Parser {    override fun handle(obj: Any): Boolean {        if (obj is Bundle) {            val s = L.getMethodNames()            println(String.format(s, parseString(obj)))            return true        }        return false    }    override fun parseString(bundle: Bundle): String {        var msg = bundle.javaClass.toString() + LoggerPrinter.BR + "║ "        val jsonObject = JSONObject()        for (key in bundle.keySet()) {            val isPrimitiveType = Utils.isPrimitiveType(bundle.get(key))            try {                if (isPrimitiveType) {                    jsonObject.put(key.toString(), bundle.get(key))                } else {                    jsonObject.put(key.toString(), JSONObject(JSON.toJSONString(bundle.get(key))))                }            } catch (e: JSONException) {                L.e("Invalid Json")            }        }        var message = jsonObject.toString(LoggerPrinter.JSON_INDENT)        message = message.replace("\n".toRegex(), "\n║ ")        return msg + message    }}

定义完各个Handler之后,需要把各个Handler串联起来。在日志类L中使用Kotlin的init代码块来做这件事,init代码块相当于Java的静态代码块。

    private val handlers = ArrayList()    private var firstHandler:BaseHandler    init{        handlers.add(StringHandler())        handlers.add(CollectionHandler())        handlers.add(MapHandler())        handlers.add(BundleHandler())        handlers.add(IntentHandler())        handlers.add(UriHandler())        handlers.add(ThrowableHandler())        handlers.add(ReferenceHandler())        handlers.add(ObjectHandler())        val len = handlers.size        for (i in 0..len - 1) {            if (i > 0) {                handlers[i - 1].setNextHandler(handlers[i])            }        }        firstHandler = handlers[0]    }

做完这些之后,才能通过一行代码来处理各种对象。

firstHandler.handleObject(obj)

三. 自定义对象的解析处理

目前在框架中只能处理8种对象,或者使用默认的方式将对象打印成json风格。

如果有个性化的需求,可以自定义类来实现,只需继承BaseHandler。

例如,定义一个UserHandler

import com.safframework.log.L;import com.safframework.log.handler.BaseHandler;import org.jetbrains.annotations.NotNull;/** * Created by tony on 2017/11/27. */public class UserHandler extends BaseHandler {    @Override    protected boolean handle(@NotNull Object obj) {        if (obj instanceof User) {            User u = (User)obj;            String s = L.getMethodNames();            System.out.println(String.format(s, u.userName+":"+u.password));            return true;        }        return false;    }}

在使用UserHandler之前,使用默认的ObjectHandler将对象格式化后打印出来。L添加了UserHandler之后,再打印user对象就不再使用默认的ObjectHandler,而是使用UserHandler来格式化对象。

        User u = new User();        u.userName = "tony";        u.password = "123456";        L.json(u);        L.addCustomerHandler(new UserHandler());        L.json(u);

打印效果

用kotlin打印出漂亮的android日志(三)——基于责任链模式打印任意对象_第3张图片 自定义Handler.png

四. 总结

这篇文章应该算是很久之前两篇文章的后续,现在越来越多的工具我开始使用Kotlin来开发。

更多相关文章

  1. 基于命令行模式开发ANDROID应用
  2. Android中的设计模式--建造者模式
  3. android 对文件的操作模式
  4. android实现Parcelable序列化对象
  5. Android Intent传递对象和集合
  6. android 跳转到小米手机神隐模式
  7. android intent 传递对象需要序列化实现Parcelable接口

随机推荐

  1. mysql回表致索引失效案例讲解
  2. mysql IS NULL使用索引案例讲解
  3. mysql中TIMESTAMPDIFF案例详解
  4. 实操MySQL+PostgreSQL批量插入更新insert
  5. MYSQL row_number()与over()函数用法详解
  6. MySQL隐式类型转换导致索引失效的解决
  7. 浅谈MySQL数据查询太多会OOM吗
  8. MySQL多表连接查询详解
  9. sqlmap注入图文详解
  10. mysql之group by和having用法详解