kotlin-coroutines

Suspend coroutine until condition is true

女生的网名这么多〃 提交于 2019-12-07 02:05:32
I have a use case where I need to connect and disconnect from a class that acts as a service. Actions can be performed on the service only when the service is connected. Clients are notified when the service connects or disconnects by a callback: class Service { constructor(callback: ConnectionCallback) { ... } fun connect() { // Call callback.onConnected() some time after this method returns. } fun disconnect() { // Call callback.onConnectionSuspended() some time after this method returns. } fun isConnected(): Boolean { ... } fun performAction(actionName: String, callback: ActionCallback) { /

Exception not being caught in Coroutines

不想你离开。 提交于 2019-12-06 03:39:07
I can't seem to get my error-handling done in coroutines. I've been reading lots of articles and the exception handling documentation but I can't seem to get it working. Here's my setup: My ViewModel launches the coroutine with it's scope class MyViewModel(private var myUseCase: MyUseCase) : ViewModel() { private val viewModelJob = Job() private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob) fun doSomething() { uiScope.launch { try { myUseCase() } catch (exception: Exception) { // Do error handling here } } } } My UseCase just handles a few logic and in this case a validator of

Testing Android Room with LiveData, Coroutines and Transactions

做~自己de王妃 提交于 2019-12-06 01:22:16
I want to test my database layer and I have caught myself in a catch-22 type of a situation. The test case consists of two things: Save some entities Load the entities and assert the database mapping works as expected The problem, in short, is that: Insert is a suspend method, which means it needs to be run in runBlocking{} Query returns a LiveData of the result, which is also asynchronous. Therefore it needs to be observed. There's this SO question that explains how to do that. In order to observe the LiveData according to the above link, however, I must use the InstantTaskExecutorRule .

Using Deferred<…> in Room DAO with Kotlin Coroutines

亡梦爱人 提交于 2019-12-06 01:09:27
I'm trying to use Coroutines with a Room database in an Android project. I've found almost no documentation online, and I'm wondering if it is possible to return Deferred<> types in those methods. Something like this: @Dao interface MyObjectDAO { @Query("SELECT * FROM myObject WHERE id_myObject = :idMyObject") suspend fun readMyObjectAsync(idMyObject: Int): Deferred<MyObject> } I've tried this and I get Not sure how to convert a Cursor to this method's return type at compile time. My dependencies are: kapt 'androidx.room:room-compiler:2.1.0-alpha04' implementation 'androidx.room:room-runtime:2

Exception thrown by deferred.await() within a runBlocking treated as unhandled even after caught

旧时模样 提交于 2019-12-05 03:28:38
This code: fun main() { runBlocking { try { val deferred = async { throw Exception() } deferred.await() } catch (e: Exception) { println("Caught $e") } } println("Completed") } results in this output: Caught java.lang.Exception Exception in thread "main" java.lang.Exception at org.mtopol.TestKt$main$1$deferred$1.invokeSuspend(test.kt:11) ... This behavior doesn't make sense to me. The exception was caught and handled, and still it escapes to the top-level as an unhandled exception. Is this behavior documented and expected? It violates all my intuitions on how exception handling is supposed to

Kotlin Coroutines : Waiting for multiple threads to finish

纵然是瞬间 提交于 2019-12-05 00:14:16
问题 So looking at Coroutines for the first time, I want to process a load of data in parallel and wait for it to finish. I been looking around and seen RunBlocking and Await etc but not sure how to use it. I so far have val jobs = mutableListOf<Job>() jobs += GlobalScope.launch { processPages(urls, collection) } jobs += GlobalScope.launch { processPages(urls, collection2) } jobs += GlobalScope.launch { processPages(urls, collection3) } I then want to know/wait for these to finish 回答1: You don't

Kotlin coroutines `runBlocking`

我的未来我决定 提交于 2019-12-04 18:39:21
问题 I am learning Kotlin coroutines. I've read that runBlocking is the way to bridge synchronous and asynchronous code. But what is the performance gain if the runBlocking stops the UI thread? For example, I need to query a database in Android: val result: Int get() = runBlocking { queryDatabase().await() } private fun queryDatabase(): Deferred<Int> { return async { var cursor: Cursor? = null var queryResult: Int = 0 val sqlQuery = "SELECT COUNT(ID) FROM TABLE..." try { cursor = getHelper()

How to recover the coroutine's true call trace?

旧时模样 提交于 2019-12-03 14:00:30
问题 This is a painfully familiar problem to anyone working with async APIs: when your call encounters a failure, the async library's private thread detects it, creates an exception object, and passes it to your callback. The only info worth a dime in that exception is its message and possibly its type. The stack trace is worthless. Cross-breed that with Google Play's way of reporting the app crashes: the message is stripped and all you get is the stack trace. Now you've got nothing to go with.

Kotlin coroutines `runBlocking`

杀马特。学长 韩版系。学妹 提交于 2019-12-03 12:12:06
I am learning Kotlin coroutines. I've read that runBlocking is the way to bridge synchronous and asynchronous code. But what is the performance gain if the runBlocking stops the UI thread? For example, I need to query a database in Android: val result: Int get() = runBlocking { queryDatabase().await() } private fun queryDatabase(): Deferred<Int> { return async { var cursor: Cursor? = null var queryResult: Int = 0 val sqlQuery = "SELECT COUNT(ID) FROM TABLE..." try { cursor = getHelper().readableDatabase.query(sqlQuery) cursor?.moveToFirst() queryResult = cursor?.getInt(0) ?: 0 } catch (e:

How to use coroutines GlobalScope on the main thread?

蓝咒 提交于 2019-12-03 07:52:52
问题 I'm trying to use the latest coroutines in 0.30.0, and having trouble figuring out how to use the new scoping. In the original coroutines I could set the context with UI or CommonPool and everything worked correctly. Now I'm trying to use the GlobalScope in my ViewModel while reading from a room database, and then I want to assign the value returned to my LiveData object. I'm getting the following error when I try to set the LiveData value java.lang.IllegalStateException: Cannot invoke