The articles

Kotlin Jetpack: The Beginning

00. The Kotlin Pit Guide for Java Developers

03. Kotlin programming’s Triple Realm

04. Kotlin higher-order Functions

05. Kotlin Generics

06. Kotlin Extension

07. Kotlin Commission

preface

Coroutines are something to love and hate. Code is really cool to write, debugging is really messy.

This article will cover debugging techniques for Kotlin coroutines without touching too much on the actual coroutines. So, whether you have the basics of coroutines or not, you can read it, and if there’s a concept that you don’t understand, you can just ignore it, and I’ll go through it systematically.

This article is the foundation for our series on coroutines, which will be followed by our part, Illustrated Coroutines. For a detailed writing plan, see Kotlin Jetpack In Action: Table of Contents.

2. Prepare

  • Update the Android Studio version to the latest
  • Clone our Demo project locally and open it with Android Studio:

Github.com/chaxiu/Kotl…

  • Switch to branch:chapter_08_coroutine_debug
  • I strongly suggest that you follow this article to practice, the actual combat is the essence of this article

3. Coroutine JVM parameters

Coroutines can be understood as lightweight threads. The relationship between coroutines and threads is a bit like the relationship between threads and processes.

When writing concurrent Java code, we often use thread.currentthread ().name to print out the name of the currentThread and log to see how it works.

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
    final int index = i;
    fixedThreadPool.execute(new Runnable() {
        @Override
        public void run(a) {
            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
*/
Copy the code

We can do something similar with Kotlin coroutines. Particular way is to add the JVM parameters: – Dkotlinx. Coroutines. Debug. Specific practices are as follows:

  • 1. Click IDEEdit Configurations

  • 2.-Dkotlinx.coroutines.debugFill in theVM optionsIn:

After adding this parameter, thread.currentThread ().name will automatically print us the name of the current coroutine.

// If you can't read this code, just ignore it
// Please look directly at the output information and comments
fun main(a) {
    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)
        }
    }
}

/* / Main @coroutine#4 MSG =2 main @coroutine#3 MSG =3 main @coroutine#2 MSG =4 */
Copy the code

summary

  • One thread can have multiple coroutines
  • Coroutines divide threads into smaller units
  • The relationship between coroutines and threads is a bit like the relationship between threads and processes.

Some people might say, “I still don’t understand what coroutines are. What’s the point of writing a log?” .

Indeed, WHEN I first learned coroutines, I had the same problem, coroutines were too abstract, more abstract than threads. The Kotlin compiler hides the underlying details of the Thread.

So, is there a more intuitive way to debug coroutines? Some, just at present the person that home knows should not much.

The other day I read on Kotlin’s official blog that they have added a lot of support for coroutine debugging in version 1.4. Although Kotlin 1.4 is not officially released yet, we can get a sneak peek at the RC Release Candidate Version.

4. Kotlin 1.4 Coroutine debugging

The thing that surprised me most about Kotlin 1.3 was Flow, and the thing that surprised me most about Kotlin 1.4 was “coroutine debugging support.”

Prior to Kotlin 1.4, I had always looked at coroutines in terms of JVM parameters, which was not friendly, and sometimes I had to add a lot of irrelevant logs in order to understand the code of coroutines.

Take a look at the changes to Kotlin 1.4:

Kotlin before 1.4 Kotlin 1.4
The breakpoint Breakpoints often do not work stable
Step through Single-step debugging often does not work stable
A separate coroutine debugging window Does not support support
View the coroutine creation stack Does not support support
Look at the coroutine call stack Does not support support
Coroutine pending state Does not support support
Coroutine memory information dump Does not support support

Although Kotlin 1.4 has not been released yet, that doesn’t stop us from exploring Kotlin 1.4 ahead of time.

4-1 Upgrade Kotlin

First, update the Kotlin-related libraries to the latest: 1.4-RC

    const val kotlinVersion = "1.4.0 - rc"
    const val coroutines = "1.3.8-1.4.0 - rc"
Copy the code

4-2 Kotlin EAP channel

Next, we need to upgrade the version of the Kotlin plug-in that comes with the IDE:

  • 1.Enter first:Configure Kotlin Plugin Updates

  • 2.Then, on the next page, inUpdates channelSelect from the drop-down box:X 1.4., click check(ladder required), and the IDE will prompt you for a new version of Kotlin. You click:installInstall and reboot.(This step can be omitted if version 1.4 has been released as you read this article. Just make sure your IDE is up to date.

4-3 breakpoint setting for coroutines

  • 3.Next, find our sample code in the IDE, hit a breakpoint, andRight click on theBreakpoint, in the pop-up box according to the following Settings:

4-4 Coroutine debugging window

  • 4.Then you can start debugging, as soon as the program stops at the breakpoint. So far, we haven’t seen the coroutine debugwindow we want, so we need to manually click on the red arrow:

  • 5.In the popup window, we need to checkcoroutines:

4-5 Debug stack for coroutines

  • 6.Once checked, we should immediately see a debug box dedicated to coroutines:

In the debug box above, we can see that our code currently has three coroutines, where position 1 represents: Corouine2. The state of coroutine3 is Suspend. The position of 2 indicates that corouine4 is in Running state. Position 3 is the creation stack of the coroutine.

4 to 6 coroutines Dump

  • 7.As I said earlier, coroutines are a lot like threads, so their debug boxes are similar. For example, you canDumpMemory state of the current coroutine for easy analysis.

Since we are not using the official version, the Dump information is still relatively little, I believe that the official support for coroutine debugging will be better and better.

5. To summarize

  • To do a good job, he must sharpen his tools. Before formally learning coroutines, we first learn coroutine debugging skills, which will be of great help to us later learning coroutines.
  • Coroutines, it’s not a monster, you can really think of it as a kind of, rightMore lightweight threads. I’m going to say this again and again, but something that looks complicated is incredibly simple, and that’s what coroutines look like.
  • This article uses1.4-rcBlogging for research is fine, but not recommended in a production environment.

All see this, give it a thumbs up!

In the next chapter, we will begin our illustrated coroutines journey.

【Kotlin Jetpack 】