In Kotlin Coroutines, the author gives this example to show how we can use async
to run 2 HTTP requests concurrently:
Before
“`kotlin fun showNews() { viewModelScope.launch { val config = getConfigFromApi() // 1 sec val news = getNewsFromApi(config) // 1 sec val user = getUserFromApi() // 1 sec –> total: 3 secs
view.showNews(user, news) }
} “`
After
“`kotlin fun showNews() { viewModelScope.launch { val config = async { getConfigFromApi() }
val news = async { getNewsFromApi(config.await()) } val user = async { getUserFromApi() }
view.showNews( user.await(), // 1 sec news.await() // 2 sec // --> total: parallel(1, 2) secs = max(1, 2) secs = 2 secs ) }
} “`
But this only seems to work if we use a non-blocking HTTP client API. For example, if I use URL/URLConnection, the total time will remain equal to 3 seconds as before, because:
1- URL
/URLConnection
do not have any suspendible functions/suspense points:
“`kotlin fun getUserFromApi(): String { val urlConnection = URL(someUrl).openConnection() val inputStream = urlConnection.getInputStream() val reader = BufferedReader(InputStreamReader(inputStream)) val stringBuilder = StringBuilder()
var line: String? while (reader.readLine().also { line = it } != null) { stringBuilder.append(line).append("n") } reader.close() inputStream.close() return stringBuilder.toString()
} “`
2- viewModelScope.launch { }
runs all coroutines on a single main thread.
So in order to reduce the total time from 3s to 2s, we should at least use a multi-threaded dispatcher, such as Dispatchers.IO
:
“`kotlin fun showNews() { viewModelScope.launch { val config = async(Dispatchers.IO) { getConfigFromApi() }
val news = async(Dispatchers.IO) { getNewsFromApi(config.await()) } val user = async(Dispatchers.IO) { getUserFromApi() }
view.showNews( user.await(), // 1 sec news.await() // 2 sec --> total: parallel(1, 2) secs = max(1, 2) secs = 2 secs ) }
} “`
Am I correct?
submitted by /u/Shartmagedon
[link] [comments]