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

1

11

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
Kike answered 26/11, 2018 at 17:19 Comment(0)
S
20

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()
    } 
}
Suspense answered 26/11, 2018 at 17:29 Comment(4)
how can I use that in the context of updating the textView.text? Let's say in the onclick listener in my example above, how will I be able to use this suspend function to get the data and update the textview?Kike
Extended my answer with an application of the getData() functionSuspense
That worked, thanks Rene. Does that mean that I have to implement coroutinescope in every activity that I'm going to use coroutine with?Kike
Yes you have. That is the reason, why a base class (see link) is useful.Suspense

© 2022 - 2024 — McMap. All rights reserved.