Home > Software engineering >  How to derive a variable from a coroutine?
How to derive a variable from a coroutine?

Time:11-12

I'm a beginner, sorry for the stupid question

I can easily output data from the coroutine to the View element (for example, in TextView) , but I can't save it in a variable.

p.s only if you first save it to TextView, and then get the data from there:

it doesn't work:

lateinit var bind: ActivityMainBinding
val scope = CoroutineScope(Dispatchers.Default)

var name2 = ""
var race2 = ""
var dexterity2 = ""
var wisdom2 = ""
var strength2 = ""

fun expData() {
    scope.launch {
        val apiData = URL(CHARACTER_DATA_API).readText()
        withContext(Dispatchers.Main) {
            var spl = apiData.split(",")
            
**Log.d("MyTag","spl:${spl}")**
            
            name2 = spl[0]
            race2 = spl[1]
            dexterity2 = spl[2]
            wisdom2 = spl[3]
            strength2 = spl[4]
            
**Log.d("MyTag","spl val:${spl[0]},${spl[1]},${spl[2]},${spl[3]},${spl[4]}")**
        }
    }
}

        bind.butGenerate.setOnClickListener {
            expData()

**Log.d("MyTag","names var: ${name2},${race2},${dexterity2},${wisdom2},${strength2}")**
            }

logs:

  1. spl:[halfling, Heavenly Baker, 15, 17, 7]
  2. spl val:halfling,Heavenly Baker,15,17,7
  3. names var:,,,,

I suffer for the second day, I can't find the answer. how to do it right. please help! (Т_Т)

it works:

lateinit var bind: ActivityMainBinding
val scope = CoroutineScope(Dispatchers.Default)

fun fetchCharacterData(bind: ActivityMainBinding){
    scope.launch {
        val apiData = URL(CHARACTER_DATA_API).readText()
        withContext(Dispatchers.Main) {
            val spl = apiData.split(",")
            bind.run {
                txtName.text = spl[0]
                txtRace.text = spl[1]
                txtDexterity.text = spl[2]
                txtWisdom.text = spl[3]
                txtStrength.text = spl[4]

        }
    }
}

and it works:

lateinit var bind: ActivityMainBinding
val scope = CoroutineScope(Dispatchers.Default)

fun fetchCharacterData(bind: ActivityMainBinding){
    scope.launch {
        val apiData = URL(CHARACTER_DATA_API).readText()
        withContext(Dispatchers.Main) {
            val spl = apiData.split(",")
            bind.run {
                txtName.text = spl[0]
                txtRace.text = spl[1]
                txtDexterity.text = spl[2]
                txtWisdom.text = spl[3]
                txtStrength.text = spl[4]

        }
    }
}

val name = bind.txtName.text
val race = bind.txtRace.text
val dex = bind.txtDextirity.text
val wis = txtWisdom.text
val str = txtStrength.text

but it seems to me that this is very long and not correct!

CodePudding user response:

In the following code:

bind.butGenerate.setOnClickListener {
    expData()

    **Log.d("MyTag","names var: ${name2},${race2},${dexterity2},${wisdom2},${strength2}")**
}

you launch a coroutine in expData() method and log the results just after that. That won't work, because coroutines are asynchronous and variables will be empty when reaching the log statement.

If you want to execute some code just after the variables have been initialized you need to do it in the coroutine block:

bind.butGenerate.setOnClickListener {
    scope.launch {
        val apiData = URL(CHARACTER_DATA_API).readText()
        withContext(Dispatchers.Main) {
            var spl = apiData.split(",")
                    
            name2 = spl[0]
            race2 = spl[1]
            dexterity2 = spl[2]
            wisdom2 = spl[3]
            strength2 = spl[4]
        }

        // ... EXECUTE YOUR CODE HERE
        // ALL VARIABLES WILL BE INITIALIZED HERE

        Log.d("MyTag","names var: ${name2},${race2},${dexterity2},${wisdom2},${strength2}")
    }
}
  • Related