Sam Garfinkel
03/25/2020, 2:32 PMCoroutineScope
(with a delegate) on a class so that you can use Deferred
as the value of its properties? This is kind of useful for creating lazily computed properties that are backed by network I/O (I’m using Ktor):
class Foo(val client: HttpClient) : CoroutineScope by GlobalScope {
val bar: Deferred<String> by lazy {
async {
client.get<String>("<https://www.example.com>")
}
}
}
bar
but I only want to compute bar
when needed.streetsofboston
03/25/2020, 2:33 PMAdam Powell
03/25/2020, 2:34 PMsuspend fun
, not a Deferred
. Deferred
is the implementation detail hereSam Garfinkel
03/25/2020, 2:35 PMsuspend fun
would compute the result each time. How would I implement the lazy functionality?streetsofboston
03/25/2020, 2:35 PMsuspend fun
can call await()
on the deferredAdam Powell
03/25/2020, 2:35 PMDeferred
because then anyone can .cancel()
it 🙂Sam Garfinkel
03/25/2020, 2:36 PMsuspend fun foo() = client.get<String>("<https://www.example.com>")
would compute it each time.client.get
since it’s expensive.Adam Powell
03/25/2020, 2:36 PMsuspend fun foo() = privateDeferredVal.await()
would not.Sam Garfinkel
03/25/2020, 2:38 PMval
private? I did that, I think I just forgot that in the example. So updated example:
private val bar: Deferred<String> by lazy {
GlobalScope.async {
client.get<String>("<https://www.example.com>")
}
}
Is this the correct design?Adam Powell
03/25/2020, 2:39 PMGlobalScope
into a private val passed to the constructor insteadSam Garfinkel
03/25/2020, 2:40 PMAdam Powell
03/25/2020, 2:41 PMGlobalScope
it's probably wrong and you'll be on the right track more often than not 🙂 you also generally want your callers to be able to provide scopes to work in rather than hardcoding themSam Garfinkel
03/25/2020, 2:42 PMAdam Powell
03/25/2020, 2:46 PMSam Garfinkel
03/25/2020, 2:49 PMbar
in that example, from suspendable functions.Adam Powell
03/25/2020, 2:51 PMSam Garfinkel
03/25/2020, 2:57 PMzak.taccardi
03/25/2020, 5:49 PMby lazy { .. }
. Try async(start = CoroutineStart.LAZY) { .. }
instead
This will avoid executing the coroutine until .await()
is calledSam Garfinkel
03/25/2020, 6:28 PMAdam Powell
03/25/2020, 7:18 PMstreetsofboston
03/25/2020, 7:20 PMasync
until the bar
is accessed for the first time, not kick it off immediately during the initialization of Foo
Adam Powell
03/25/2020, 8:34 PM