Here's an example from developer.android.com
class MainActivity : AppCompatActivity() {
lateinit var textView:TextView
lateinit var button:Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textView = findViewById(R.id.textView)
button = findViewById(R.id.button)
button.setOnClickListener({
getData()
})
}
fun getData(){
val queue = Volley.newRequestQueue(this)
val url = "http://www.google.com/"
val stringRequest = StringRequest(Request.Method.GET, url,
Response.Listener<String> { response ->
textView.text = "Response is: ${response.substring(0, 500)}"
},
Response.ErrorListener { textView.text = "Something went wrong!" })
queue.add(stringRequest)
}
}
How can I take advantage of coroutines so I can write my code in this manner:
val data = getData()
textView.text = data
On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive. Over 50% of professional developers who use coroutines have reported seeing increased productivity.
Coroutines can be executed concurrently using a multi-threaded dispatcher like the Dispatchers.
A coroutine internally uses a Continuation class to capture the contexts for its execution. Then the dynamic aspect is modeled as a Job class. The use of async usually creates a Deferred job, which is a subclass of the Job class. The CoroutineContext type is required for a coroutine to execute.
Main thread is cooperative, it allows scheduling of tasks and coroutines just use this feature. Also, you asked in the comments, how is it possible that both log statements are run in parallel, but on the same thread. They are not run in parallel.
You can use suspendCoroutine
, see https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/suspend-coroutine.html
suspend fun getData() = suspendCoroutine<String> { cont ->
val queue = Volley.newRequestQueue(this)
val url = "http://www.google.com/"
val stringRequest = StringRequest(Request.Method.GET, url,
Response.Listener<String> { response ->
cont.resume("Response is: ${response.substring(0, 500)}")
},
Response.ErrorListener { cont.resume("Something went wrong!") })
queue.add(stringRequest)
}
You should implement your activity like described here: https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/coroutines-guide-ui.md#structured-concurrency-lifecycle-and-coroutine-parent-child-hierarchy
class MainActivity: AppCompatActivity(), CoroutineScope {
protected lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
job = Job()
...
button.setOnClickListener({
launch {
val data = getData()
textView.text = data
}
})
}
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With