Challenge: Minimum Strength

Here is my solution, any feedback is highly appreciated:

private fun updateCharacterFromWeb() {
    GlobalScope.launch(Dispatchers.Main) {
        characterData = fetchCharacterDataAsync().await()
        characterData.str.toInt().let {
            when {
                it < 10 -> updateCharacterFromWeb()
                else -> displayCharacterData()
            }
        }
    }
}

I haven’t traced the threads all the way through, but I worry about making the recursive call by continuing to launch new coroutines.

My solution is similar, but puts a loop inside the launch() routine instead of the recursive call back to the function.

private fun fetchCharacterFromAPIAsync() = CoroutineScope(Dispatchers.Main).launch {
    try {
        // display the "Generating Character" message while blocking call executes
        characterData = CharacterGenerator.placeHolderCharacter()
        displayCharacterData()

        do {
            // fetchCharacterData() is a suspend function - it is a blocking call
            characterData = fetchCharacterDataBlocking()    // perform the API call
            // code will continue when blocking call completes
        } while (characterData.str.toInt() < 10)

        Log.d(LOG_TAG, "fetchCharacterFromAPIAsync() received valid character")

        // display the network queried character
        displayCharacterData()
    } finally {
        Log.d(LOG_TAG, "fetchCharacterFromAPIAsync() finally block")
    }
}

private suspend fun fetchCharacterDataBlocking() = withContext(Dispatchers.IO) {
    val apiData = URL(CHARACTER_DATA_API).readText()
    CharacterGenerator.fromApiData(apiData)
}

Here’s my solution.

CharacterGenerator.kt

At first, I put the loop in the suspend method fetchCharacterData()

suspend fun fetchCharacterData(): CharacterGenerator.CharacterData {

    var characterData: CharacterGenerator.CharacterData

    while (true) {

        val apiData = withContext(Dispatchers.IO) {
            URL(CHARACTER_DATA_API).readText()
        }

        characterData = CharacterGenerator.fromApiData(apiData)

        if (characterData.str.toInt() >= 10) {
            break
        }
    }

    return characterData
}

NewCharacterActivity.kt

Then, just call fetchCharacterData() without outer loop in the NewCharacterActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_new_character)

        GlobalScope.launch(Dispatchers.Main) {
            characterData = savedInstanceState?.characterData ?: fetchCharacterData()
            displayCharacterData()
        }

        generateButton.setOnClickListener {
            GlobalScope.launch(Dispatchers.Main) {
                characterData = fetchCharacterData()
                displayCharacterData()
            }
        }
    }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_character)
do {
characterData = savedInstanceState?.characterData ?: runBlocking { fetchCharaterData().await() }
} while (characterData.str.toInt() < 10)
displayCharacterData()
generateButton.setOnClickListener {
runBlocking {
do {
characterData = fetchCharaterData().await()
} while (characterData.str.toInt() < 10)

            displayCharacterData()
        }
    }
}

Hi!
At first I updated syntax of coroutines as shown here:
Coroutines 1.3.5

Then I implemented the mentioned below:

fun fetchCharacterData(): Deferred<CharacterGenerator.CharacterData> {
    var str1 = 0
    var res = ""
    return GlobalScope.async {
        while(str1<10)
        {
            res = URL(CHARACTER_DATA_API).readText()
            str1 = CharacterGenerator.fromApiData(res).str.toInt()
        }
        CharacterGenerator.fromApiData(res)
    }
}

but I believe that it can be realized in Functional programming style…