https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
j

jared

11/18/2020, 5:53 PM
I am using
kotlinx.coroutines
1.3.9-native-mt-2
and Ktor
1.4.2
in a multiplatform library for sharing networking between iOS and Android. I am confused over Ktor and background threads. I am using the
Main
dispatcher and I can’t tell if the network request is running on the main thread or a background thread. Does Ktor handle running a single background thread for me?
j

John O'Reilly

11/18/2020, 6:10 PM
Yes, Ktor is "main-safe"
j

jared

11/18/2020, 6:30 PM
@John O'Reilly I am confused on iOS, not Android. If I call a Ktor network request using the main dispatcher will Ktor actually run the request on a blocking background thread or the UI thread?
j

John O'Reilly

11/18/2020, 6:31 PM
Yes, this main-safety applies to both Android and iOS....I used that link to just explain what that was just in case it wasn't familiar
it will run request on non-UI dispatcher
using I presume something like
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
under the hood
d

Daniele B

11/18/2020, 6:39 PM
@John O'Reilly so is Ktor actually using "WithContext" to change dispatcher under the hood? I find a bit confusing the fact that the context you define in your coroutine to launch a suspend function is eventually not the one the suspend function runs on.
👆 1
j

John O'Reilly

11/18/2020, 6:39 PM
@Daniele B this is the key mechanism used to provide "main-safety"
d

Daniele B

11/18/2020, 6:49 PM
@John O'Reilly very interesting though! This means that in a ViewModel that needs to call a DataLayer's suspend function, we can always launch the coroutine in the Main thread, without having to know and match which thread the DataLayer's suspend functions will actually use. It's very practical. And it makes sense.
j

John O'Reilly

11/18/2020, 6:50 PM
yeah, I think it's a nice approach
j

jared

11/18/2020, 6:51 PM
On Android I ended up using
withContext(<http://Dispatches.IO|Dispatches.IO>)
because StrictMode was complaining about reading from disk when the Ktor
HttpClient
was initialized. That confused me, but if Ktor was running the request on the main thread then I would assume a NetworkOnMainThread exception would be thrown.
j

John O'Reilly

11/18/2020, 6:51 PM
@Daniele B that link I posted above has an example that does just that
d

Daniele B

11/18/2020, 6:55 PM
@John O'Reilly thanks, so it's not a mystery anymore why Ktor works without blocking the main thread. I had assumed it was because running small network calls on the main thread wouldn't actuallt block it. Only now I find out that it's because Ktor is actually changing the context under the hood!
j

John O'Reilly

11/18/2020, 7:05 PM
For example the following are logs for run I did just now using ktor on JVM
Copy code
[main] INFO io.ktor.client.HttpClient - REQUEST: <http://api.open-notify.org/astros.json>
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Accept: application/json
[main] INFO io.ktor.client.HttpClient - -> Accept-Charset: UTF-8
[main] INFO io.ktor.client.HttpClient - CONTENT HEADERS
[main] INFO io.ktor.client.HttpClient - BODY Content-Type: null
[main] INFO io.ktor.client.HttpClient - BODY START
[main] INFO io.ktor.client.HttpClient - 
[main] INFO io.ktor.client.HttpClient - BODY END
[main] INFO io.ktor.client.HttpClient - RESPONSE: 200 OK
[main] INFO io.ktor.client.HttpClient - METHOD: HttpMethod(value=GET)
[main] INFO io.ktor.client.HttpClient - FROM: <http://api.open-notify.org/astros.json>
[main] INFO io.ktor.client.HttpClient - COMMON HEADERS
[main] INFO io.ktor.client.HttpClient - -> Connection: keep-alive
[main] INFO io.ktor.client.HttpClient - -> Content-Length: 356
[main] INFO io.ktor.client.HttpClient - -> Content-Type: application/json
[main] INFO io.ktor.client.HttpClient - -> Date: Wed, 18 Nov 2020 19:04:33 GMT
[main] INFO io.ktor.client.HttpClient - -> Server: nginx/1.10.3
[main] INFO io.ktor.client.HttpClient - -> access-control-allow-origin: *
[ktor-apache-dispatcher-worker-2] INFO io.ktor.client.HttpClient - BODY Content-Type: application/json
[ktor-apache-dispatcher-worker-2] INFO io.ktor.client.HttpClient - BODY START
[ktor-apache-dispatcher-worker-2] INFO io.ktor.client.HttpClient - {"message": "success", "number": 7, "people": [{"craft": "ISS", "name": "Sergey Ryzhikov"}, {"craft": "ISS", "name": "Kate Rubins"}, {"craft": "ISS", "name": "Sergey Kud-Sverchkov"}, {"craft": "ISS", "name": "Mike Hopkins"}, {"craft": "ISS", "name": "Victor Glover"}, {"craft": "ISS", "name": "Shannon Walker"}, {"craft": "ISS", "name": "Soichi Noguchi"}]}
[ktor-apache-dispatcher-worker-2] INFO io.ktor.client.HttpClient - BODY END
you can see initial logs on
main
but then actualy request is made on
ktor-apache-dispatcher-worker-2
d

Daniele B

11/18/2020, 7:10 PM
It looks like HTTP headers are retrieved on Main, and the HTTP body on a background thread
j

John O'Reilly

11/18/2020, 7:12 PM
I think the logs might be a bit out of sequence.....my understanding is that it's only the logging of that header info that's happening on main thread
j

jared

11/18/2020, 7:17 PM
Perhaps that’s the
HttpRequestBuilder
running on main.
Thank you @John O'Reilly for the feedback here
d

Daniele B

11/18/2020, 7:24 PM
I trust Ktor is doing it in the most effective way. The key takeaway is that it's clearly switching the execution thread at a certain point. This is a very important pattern which makes sense to apply at an architectural level for our apps. Designing ViewModels that just launch coroutines in the main thread. Designing DataLayer functions that select the appropriate thread by using "withContext".
👍 1
a

Amritansh

11/19/2020, 12:37 AM
You can also explicitly use withContext(Dispatcher.Default) to switch to a different thread. Coroutine for kotlin native support switching between Main and Default
3 Views