Home > Software design >  Android Basics in Kotlin: confused by Introduction to Debugging
Android Basics in Kotlin: confused by Introduction to Debugging

Time:03-19

I have a very basic question. I'm following through the development guide codelabs in the suggested order, and failing at "Intro To Debugging" section 6: "Record a Running App". I find the explanation very confusing because rather minimal for a beginner.

I'm happy to delete and start again if something doesn't work as expected, but I also need to be sure that as I progress, any lack of desired result isn't due to my environment.

In this lesson we are required to modify existing code to update the apps single TextView using a Log.d statement such that we see the ID division_textview updated on the phone screen.

I have tried numerous ways to add the final statement

findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")

but cannot add it anywhere such that the values are updated in my emulator. I get no errors but since there is no "solution code" in this lesson, and the lesson's preceding images all serve to rather muddy the picture of exactly how the final code should look, could someone please help me with this?

I really need to be sure my emulator works correctly (there are no errors reported) and that lack of results is my code and not my setup.

This is the lesson in question (thanks for the tip!)

lesson

Code from my MainActivity.kt further to helpful suggestion below. Please note that I realise it's not 'optimal' code, I'm simply attempting to follow instructions at this point.

package com.example.debugging

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView

private const val TAG = "MainActivity"

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val helloTextView: TextView = findViewById(R.id.division_textview)
        helloTextView.text = "Hello, debugging!"
        logging()
        division()
    }

    fun division() {
        val numerator = 60
        var denominator = 4
        repeat(4) {
            Thread.sleep(3)
            findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
            Log.v(TAG, "${numerator / denominator}")
            denominator--
        }
    }

    fun logging() {
            Log.e(TAG, "ERROR: a serious error like an app crash")
            Log.w(TAG, "WARN: warns about the potential for serious errors")
            Log.i(TAG, "INFO: reporting technical information, such as an operation succeeding")
            Log.d(TAG, "DEBUG: reporting technical information useful for debugging")
            Log.v(TAG, "VERBOSE: more verbose than DEBUG logs")
        }
    }

CodePudding user response:

I think this is a very sloppily written and incorrect tutorial. (Yes, even though it's from Google.) If you sleep in the main thread, you're not going to see the text view content change until the entire repeat loop is done, so you will only see the final value, after denominator has already been decremented to 0. Also, the tutorial claims you will see it change every three seconds even though the code with Thread.sleep(3) would only pause for 3 milliseconds. And then in their actual example, they used Thread.sleep(1), which contradicts their instructions.

Try this code instead:

// added to imports:
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.*

// modified division function
fun division() = lifecycleScope.launch {
    val numerator = 60
    var denominator = 4
    repeat(4) {
        delay(3000)
        findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
        Log.v(TAG, "${numerator / denominator}")
        denominator--
    }
}

Using = lifecycleScope.launch { turns your function into a coroutine which lets you use the delay() function instead of Thread.sleep(), so the main thread is given the opportunity to actually update your text view instead of having to wait for the whole repeat loop to finish.


Here's an alternate way to do it without coroutines, but it's not as pretty:

fun division() = with(Handler(Looper.getMainLooper())) {
    val numerator = 60
    var denominator = 4
    repeat(4) { i ->
        postDelayed({
            findViewById<TextView>(R.id.division_textview).setText("${numerator / denominator}")
            Log.v(TAG, "${numerator / denominator}")
            denominator--
        }, i * 3000L)
    }
}
  • Related