Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use coroutines with volley so that my code can be written like sychronous?

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
like image 358
Lance Avatar asked Nov 26 '18 17:11

Lance


People also ask

What are kotlin coroutines good for?

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.

Do coroutines run concurrently?

Coroutines can be executed concurrently using a multi-threaded dispatcher like the Dispatchers.

How are coroutines implemented?

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.

Is coroutines run on main thread?

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.


1 Answers

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()
    } 
}
like image 95
Rene Avatar answered Sep 28 '22 00:09

Rene