I have some code that 1] fetches a JSON file and 2] depending on the content of that JSON file, fetches another JSON file. It uses the ion library.
The code roughly looks like this (Sidenote - this code is on the onCreate
method of my activity and e
is an object of the type Exception
):
Ion.with(applicationContext)
.load("someURL")
.asJsonObject()
.setCallback { e, result->
//Do synchronous stuff with the "result" and "e" variables
//that determines whether boolean someCondition is true or false
if(somecondition) {
Ion.with(applicationContext)
.load("https://raw.githubusercontent.com/vedantroy/image-test/master/index.json")
.asJsonObject()
.setCallback { e, result ->
//Some synchronous code in here
}
}
}
This code is very ugly, and I'd like to improve it in order to get rid of the nesting. Is that possible, and if so, how would I do it?
I've been experimenting and it seems I can call the method .then()
after setCallback
like so, where .then()
accepts a parameter that is a callback
object:
Ion.with(applicationContext).load("someURL").setCallback { //Lambda Stuff }.then()
so maybe that will be part of the solution, but I'm not sure.
The Ion project has a module for Kotlin coroutines: https://github.com/koush/ion/tree/master/ion-kotlin, but it doesn't seem to be in a production state. Luckily, it is very simple to add your own bridge between any asynchronous API and Kotlin coroutines.
Here's an example of how to do it for Ion:
private suspend fun fetchIon(url: String): String = suspendCoroutine { cont ->
Ion.with(this)
.load(url)
.asString()
.setCallback { e, result ->
if (e != null) {
cont.resumeWithException(e)
} else {
cont.resume(result)
}
}
}
Now you can have code like this:
class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launch(UI) {
if (fetchIon("example.org/now") > fetchIon("example.org/deadline") {
...
}
}
}
As you can see, you execute asynchronous IO code just like it was blocking. To handle errors, just wrap it in a try-catch, as you would any "regular" code.