https://kotlinlang.org logo
#coroutines
Title
# coroutines
i

igor.wojda

12/11/2019, 4:23 PM
Is there any way to “connect” to existing running coroutine job and wait for the result? Case: Let’s say I have the same instance of repository injected into multiple different classes (
client A
,
client B
). Now
client A
calls
repository.getUserData()
and this method internally loads data from network. While request is going
cliebt B
also calls
repository.getUserData()
on the same instance of repository. Can we detekt that network call is in progress and somehow wait for it to finish and return data to both clients?
Copy code
// Client A:
CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
    reository.getUserData()
}

// Client B:
CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
    reository.getUserData()
}

class Repository() {
    private val job: Job? = null

    suspended fun getUserData() {
        if(job != null) {
            // job is already runned by other client 
            // can I some how "connect" (wait fo the result) to this job
            // instead of proceding and making new network request
        }

        job = CoroutineScope(<http://coroutineContentProvider.IO|coroutineContentProvider.IO>).launch {
            // make network call and return client data
            // return network data
        }
    }
}
b

bezrukov

12/11/2019, 4:28 PM
job.join
waits for completion, but since you need a result, you could switch from
launch
to
async
i

igor.wojda

12/11/2019, 5:06 PM
can you show me an example?
b

bezrukov

12/11/2019, 5:53 PM
based on your example:
Copy code
class Repository() {
    private val scope = CoroutineScope(SupervisorJob() + <http://Dispatchers.IO|Dispatchers.IO>)
    private var activeJob: Deferred<UserData>? = null

    suspended fun getUserData(): UserData {
        val job = activeJob ?: scope.async{
            // make network call and return client data
            // return network data
        }
        activeJob = job
        return job.await()
    }
}
what you need to consider additionally: 1. there is a race condition on active job, because getUserData is not thread(coroutine)-safe 2. clean
activeJob
when completed (or just call
activeJob?.takeIf { !it.completed }
)
5 Views