用kotlin打印出漂亮的android日志(三)——基于责任链模式打印任意对象

文章介绍了如何使用Kotlin重构SAF-Kotlin-log框架,利用责任链模式改进对象打印方法,支持Uri和Bundle等Android常用对象的格式化输出,实现了对特定类型对象的扩展和个性化打印,同时提供了自定义Handler的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

1.1 Uri的打印

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

  2.        L.json(uri);

打印效果:


1.2 Bundle的打印

  1.        User u = new User();

  2.        u.userName = "tony";

  3.        u.password = "123456";

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

打印效果:


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

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

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

  1.    /**

  2.     * 将任何对象转换成json字符串进行打印

  3.     */

  4.    @JvmStatic

  5.    fun json(obj: Any?) {

  6.        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表达式。

  1.    /**

  2.     * 将任何对象转换成json字符串进行打印

  3.     */

  4.    @JvmStatic

  5.    fun json(obj: Any?) {

  6.        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来处理。

  1. /**

  2. * Created by tony on 2017/11/27.

  3. */

  4. abstract class BaseHandler {

  5.    // 责任链的下一个节点,即处理者

    •    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并打印出来。

  1. import android.os.Bundle

  2. import com.alibaba.fastjson.JSON

  3. import com.safframework.log.L

  4. import com.safframework.log.LoggerPrinter

  5. import com.safframework.log.parser.Parser

  6. import com.safframework.log.utils.Utils

  7. import org.json.JSONException

  8. import org.json.JSONObject

  9. /**

    • * Created by tony on 2017/11/27.

    • */

    • class BundleHandler():BaseHandler(), Parser<Bundle> {

    •    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的静态代码块。

  1.    private val handlers = ArrayList<BaseHandler>()

  2.    private var firstHandler:BaseHandler

  3.    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]

        •    }

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

  1. firstHandler.handleObject(obj)

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

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

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

例如,定义一个UserHandler

  1. import com.safframework.log.L;

  2. import com.safframework.log.handler.BaseHandler;

  3. 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来格式化对象。

  1.        User u = new User();

  2.        u.userName = "tony";

  3.        u.password = "123456";

  4.        L.json(u);

  5.        L.addCustomerHandler(new UserHandler());

    •        L.json(u);

打印效果


四. 总结

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


关注【Java与Android技术栈】

更多精彩内容请关注扫码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值