美文网首页Android进阶之路Android开发Android开发经验谈
Kotlin Jetpack 实战 | “不为人知”的协程调试技

Kotlin Jetpack 实战 | “不为人知”的协程调试技

作者: Android进阶小麦 | 来源:发表于2020-08-17 17:00 被阅读0次

    前言

    协程(Coroutines),是个让人又爱又恨的东西。代码写起来是真的,调试起来是真的

    本文将介绍 Kotlin 协程的调试技巧,不会涉及太多协程实际内容。所以,不管你有没有协程的基础,都可以看下去,如果有遇到不懂的概念直接忽略即可,后面我会系统讲解。

    这篇文章是为我们协程系列打基础的,后面进入我们的协程部分《图解协程》,具体的写作计划大家可以到这里看看:《Kotlin Jetpack 实战:目录》,欢迎提建议。

    2. 前期准备

    • 将 Android Studio 版本升级到最新
    • 将我们的 Demo 工程 clone 到本地,用 Android Studio 打开: github.com/chaxiu/Kotl…
    • 切换到分支:chapter_08_coroutine_debug
    • 强烈建议各位小伙伴小伙伴跟着本文一起实战,实战才是本文的精髓

    3. 协程 JVM 参数

    协程,可以理解为轻量级的线程。协程跟线程的关系,有点像“线程与进程的关系”。

    在我们写 Java 并发代码的时候,我们经常会用 Thread.currentThread().name 带打印出当前线程的名字,然后通过日志来查看运行效果。

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
    for (int i = 0; i < 10; i++) {
        final int index = i;
        fixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println(Thread.currentThread().getName() + "index = " + index);
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    /*
    pool-1-thread-1index = 0
    pool-1-thread-3index = 2
    pool-1-thread-2index = 1
    pool-1-thread-2index = 3
    pool-1-thread-3index = 4
    */
    复制代码
    

    对于 Kotlin 协程,我们也可以做类似的事情。具体做法是,添加 JVM 参数:-Dkotlinx.coroutines.debug。具体做法如下:

    • 1.点击 IDE 的 Edit Configurations
    • 2.将-Dkotlinx.coroutines.debug填入 VM options 中:

    在加上这个参数以后, 我们通过 Thread.currentThread().name,就会自动为我们输出当前协程的名字。

    // 这段代码看不懂没关系,忽略即可
    // 请直接看后面的输出信息和注释
    fun main() {
        runBlocking<Unit> {
            fun log(msg: Any) {
                println("${Thread.currentThread().name} msg=$msg")
            }
    
            log(1)
    
            launch {
                val a = 4
                delay(300)
                log(a)
            }
            launch {
                val b = 3
                delay(200)
                log(b)
            }
            launch {
                val c = 2
                delay(100)
                log(c)
            }
        }
    }
    
    /*
    // 输出:
    
    1个线程   4个协程
     ↓         ↓
    main @coroutine#1 msg=1
    main @coroutine#4 msg=2
    main @coroutine#3 msg=3
    main @coroutine#2 msg=4
    */
    复制代码
    

    小结

    • 一个线程可以对应多个协程
    • 协程将线程划分成更小的单元
    • 协程跟线程的关系,有点像“线程与进程的关系”。

    看到这里,也许会有小伙伴说:“我还是搞不懂协程到底是什么,输出一个日志,能说明什么问题呢?”

    确实,我在刚学习协程的时候,也有这种苦恼,协程太抽象了,比线程还抽象。线程它起码有一个 Thread.java 的源码给你看,协程呢,没有,Kotlin 编译器将它底层细节都屏蔽了。

    那么,有没有更直观的方式来调试协程呢?有的,只是目前国内知道的人应该不多。

    前几天我在 Kotlin 官方的博客 中了解到:Kotlin 官方在 1.4 版本中为协程调试增加了许多支持。虽然 Kotlin 1.4 现在还没正式发布,但是我们可以抢先体验它的 RC 版本(Release Candidate Version)。

    4. Kotlin 1.4 协程调试

    Kotlin 1.3 最让我惊喜的是 Flow,而 Kotlin 1.4 最让我惊喜的则是“协程调试支持”

    在 Kotlin 1.4 之前,我一直都是通过 JVM 参数来研究协程的,这种方式并不友好,有的时候为了理解协程的代码,我需要加很多无关的 log。

    一起看看 Kotlin 1.4 的变化:

    Kotlin 1.4 之前 Kotlin 1.4
    断点 断点经常不生效 稳定
    单步调试 单步调试经常不生效 稳定
    单独的协程调试窗口 不支持 支持
    查看协程创建栈 不支持 支持
    查看协程调用栈 不支持 支持
    协程挂起状态 不支持 支持
    协程内存信息 dump 不支持 支持

    虽然 Kotlin 1.4 尚未发布,但这并不影响我们提前探索使用 Kotlin 1.4,毕竟早用早享受嘛。

    4-1 升级 Kotlin 版本

    首先,将 Kotlin 相关的库升级到最新的:1.4-RC

        const val kotlinVersion = "1.4.0-rc"
        const val coroutines = "1.3.8-1.4.0-rc"
    复制代码
    

    4-2 Kotlin EAP 渠道

    接下来,我们需要升级 IDE 自带的 Kotlin 插件版本:

    • 1.首先进入:Configure Kotlin Plugin Updates
    • 2.然后,在接下来的页面中,在 Updates channel 下拉框中选择:1.4.x,点击 check(需要梯子),接着 IDE 会提示你有新的 Kotlin 版本,你点击:install 安装,然后重启即可。(如果你在看这篇文章的时候,1.4 正式版已经发布了的话,这一步就可以省略了。你只需要确保 IDE 是最新的即可。)

    4-3 协程的断点设置

    • 3.接下来在 IDE 中找到我们的示例代码,打一个断点,然后右键点击断点,在弹出框中按照如下设置:

    4-4 协程调试窗口

    • 4.然后就可以开始调试了,等程序停留在断点的位置后,会是这样。到目前为止,都还没有看见我们想要的协程调试窗,这时候需要我们手动点击红色箭头的位置:
    • 5.在弹出的窗口中,我们需要勾选 coroutines:

    4-5 协程的调试栈

    • 6.勾选以后,我们就立马能看到一个专属于协程的调试框:

    在上面的调试框中,我们能看到我们的代码当前有三个协程,其中1的位置,代表:corouine2, coroutine3 的状态是 Suspend2的位置,代表corouine4 的状态是 Running3的位置,是该协程的创建栈。

    4-6 协程 Dump

    • 7.正如我前面所说的,协程跟线程很像,所以它们两者的调试框也是类似的。比如,你还可以 Dump 当前协程的内存状态,方便分析。

    由于我们使用的并非正式的版本,Dump 出来的信息还比较少,相信之后官方对协程调试的支持会越来越好。

    5. 总结

    • 工欲善其事,必先利其器。在正式学习协程之前,我们先学会协程调试技巧,这将对我们后面学习协程有极大的帮助。
    • 协程,并不是什么洪水猛兽,你完全可以将它看作一种更轻量级的线程。这句话我以后会反复讲,有些东西看起来复杂,本质却极其简单,协程就是这样的。
    • 本文使用的是 1.4-rc 版本,写博客做研究是没问题的,但在生产环境是不推荐使用的。

    觉得有用的话,点个赞吧~~也欢迎在下方评论,提出你的见解。

    相关文章

      网友评论

        本文标题:Kotlin Jetpack 实战 | “不为人知”的协程调试技

        本文链接:https://www.haomeiwen.com/subject/asvqjktx.html