Paul Woitaschek
09/14/2019, 7:16 AMAllan Wang
09/14/2019, 7:18 AMoctylFractal
09/14/2019, 7:18 AMasync { cont.resume() } I suppose, but it doesn't return a value, so you probably want to use launch & join. Seems like an XY problem though.Paul Woitaschek
09/14/2019, 7:19 AMPaul Woitaschek
09/14/2019, 7:21 AMoctylFractal
09/14/2019, 7:24 AMJob, which you can already join on.
A better model for your case might be to use an actor for each code, so that all permission requests are automatically processed sequentially. Then you don't have to wait for anything.Paul Woitaschek
09/14/2019, 7:26 AMsuspendCancellableCoroutine gives me a continuation and that's exactly what I needelizarov
09/14/2019, 7:33 AMCompletableDeferred whould be a much better fit. Use and store them instead of continuations, and you'll have no problem waiting for the same one multiple times.Paul Woitaschek
09/14/2019, 7:35 AMsuspend fun request(permission: String): PermissionResult
So I need to store what kind of permission I was requesting, right?elizarov
09/14/2019, 7:37 AMsuspend fun request(permission: String) =
mapPermissionToDeferred.getOrPut(permsision) {
requestPermission(permission)
}.await()elizarov
09/14/2019, 7:39 AMuspend fun request(permission: String) =
mapPermissionToDeferred.getOrPut(permsision) {
appScope.async { requestPermission(permission) }
}.await()
where:
mapPermissionToDeferred: MutableMap<String, Deferred<PermissionResult>>
suspend fun requestPermission: (permission: String): PermissionResultelizarov
09/14/2019, 7:40 AMCompletableDeferred with the last approach -- just use async with a proper application-level scope)Paul Woitaschek
09/14/2019, 7:41 AMoctylFractal
09/14/2019, 7:41 AMCompletableDeferred is on the right track. Basically, since (If I'm interpreting your words correctly) you can only call requestPermissions one at a time, you can store the requestCode & a CompletableDeferred, then in your suspend fun request, if it's non-null, await it first. Then set the request code, a new CompletableDeferred, and call requestPermission. Then await your new deferred. You might need to use a Mutex here to ensure it's concurrently-safe, or box the requests in a data object and use actor to automatically sequential-ize* it. In onRequestPermissionsResult, you can check the code against the field, then complete the deferred. No Map needed.elizarov
09/14/2019, 7:43 AMsuspend fun request from your main thread (you can wrap its body into withContext(Dispatchers.Main) { ... } to be sure, you'll never get two concurrent requests to the same permission, since the first one will get stored in the map via getOrPutPaul Woitaschek
09/14/2019, 7:43 AMoctylFractal
09/14/2019, 7:43 AMoctylFractal
09/14/2019, 7:44 AMnull out the field before setting the result. that's perfectly fine GC-wisePaul Woitaschek
09/14/2019, 7:44 AMto be sure, you'll never get two concurrent requests to the same permissionNo, I must be sure to never get two concurrent requests ever, unregarding of the permission type
elizarov
09/14/2019, 7:45 AMPaul Woitaschek
09/14/2019, 7:47 AMCompletableDeferred?Paul Woitaschek
09/14/2019, 7:47 AMPaul Woitaschek
09/14/2019, 7:48 AMelizarov
09/14/2019, 7:48 AMsuspend fun requestPermission: (permission: String, result: CompletableDeferred<PermissionResult>): PermissionResult = permission.send(permission to PermissionResult)
where
permissionActor = actor<Pair<String, PermissionResult>> {
for ((permission, result) in channel) {
val permission = getIt(...)
result.complete(permission)
mapPermissionToDeferred.remove(permission)
// ^^ this way future requests will request it again
}
}elizarov
09/14/2019, 7:49 AMCancellableContinuation with CompletableDeferred and instead of resume call complete.elizarov
09/14/2019, 7:50 AMsuspendCancellableCoroutine<Unit> { cont -> ... } you can do:
val d = CompletableDeferred<Unit> /// why unit?
...
d.await()elizarov
09/14/2019, 7:51 AMoctylFractal
09/14/2019, 7:56 AMoctylFractal
09/14/2019, 7:57 AMrequestPermissionsDeferred = null in onRequestPermissionsResult, if you wish to clean upPaul Woitaschek
09/14/2019, 8:04 AMactor.send waits till the actor is empty? How do I get a result from it?octylFractal
09/14/2019, 8:05 AMCompletableDeferred. have the actor complete itlouiscad
09/14/2019, 1:22 PM