I’m still at the stage where I’m reading about cor...
# coroutines
a
I’m still at the stage where I’m reading about coroutines rather than using it extensively, but I have a few more questions: When it comes to writing suspended functions, is there anything we should look out for in terms of potential memory leaks? If I compare Android coroutines with anko, anko tends to wrap the receiver with a weakreference, so that you can retrieve it again during your call. It’s written as type
(T) -> Unit
vs
T.() -> Unit
, which strikes me as a bit odd as anyone can use the original variable and forget about trying to get it from the weak reference. With coroutines, I don’t think weak references are used correct? Would it stand that so long as we make the coroutine scope agree to our lifecycle, we don’t have to worry about leaking variables beyond what we would normally consider when writing synchronous code? More specifically to Android, is there a general practice for writing suspended functions dealing with
Context
in a utility class where context would be passed through as an argument? Is it fine that we keep a global hashmap of deferred results if the scope cancels the job when appropriate?
g
Coroutines in anko deprecated and suggest to use async directly, so not sure what you mean. Potential coroutine memory leaks are mostly the same as any other async code. Structure concurrency forces you to use some scope and in case of Android it’s your component lifecycle, so this allow to have much more robust and safe resource and memory management Because coroutine cancellation is cooperative and if every component supports it you don’t need weak reference, because Job will be cancelled and all children coroutines of this scope. But if you use coroutines just as abstraction for threading and wrapping blocking code than yes, weak reference can be useful, because you just cannot cancel blocking code during operation
More specifically to Android, is there a general practice for writing suspended functions dealing with
Context
in a utility class where context would be passed through as an argument?
Depends how you use this context. If you don’t use any non-cancellable or blocking code in your suspend utility, than everything is finy. if you do, than you have not so many choices, one common practice for that, always get applicationContext instance from any passed context, so there is not possible to leak such global context, but this work not for all cases, sometimes you need component context.
In general, I don’t see big differences in approach comparing with other async code except that only coroutines force you to use scopes and this helps to avoid common programmer’s mistakes and do not forget bind async code to lifecycle
a
My goal wasn’t to make an argument for anko, but to see what I might have to focus on, given anko’s different structure. I was thinking of a few examples, such as passing context into suspended functions, and creating something like RxJava’s PublishSubject for js interactions in Android. For js, I can add an interface for the webview to get onclick events, then switch to the main thread to show the onclick events in the ui. It seems like in all these cases, so long as I don’t keep a global reference, everything will be okay. It was just the fact that anko wrapped the receiver with a weak reference that made me think that I might be missing something.
g
Could you show an example of such anko code? Most probably it requires only for blocking code wrapped to coroutines
given anko’s different structure.
Could you show an example?
context into suspended functions, and creating
As I said before it depends on context type (application context cannot leak) and on suspend function implementation, if all operations inside suspend function are cancelable than everything is fine even with activity context
something like RxJava’s PublishSubject
Similar approach already available in Channels API
I can add an interface for the webview to get onclick events, then switch to the main thread to show the onclick events in the ui.
But you don't need context for this task, switching of threads can be done with coroutines dispatchers
a
I have to take a look at channels and with coroutine dispatchers. My question towards anko is here: https://github.com/Kotlin/anko/issues/496 If it’s safe to use context within anko’s async code, why did they have to wrap it in a weak reference? Their
uiThread
method also checks if the weak reference still exists, so how does that differ with coroutines? My current logic all use view post runnables, Rx, and anko. The questions I have for coroutines are the same as I’d have for my current code, though as I make the transition I just want to make sure that I do everything properly.
g
Because it depends on function, sometimes it’s safe, sometimes it doesn’t. If you have blocking operation or non-cancellalbe async than context will leak during this optetaion
Also just checked what is
doAsync
and it’s not coroutine! This is just a wrapper from ExecutorService that runs on thread executor and you cannot cancel it (you cannot just stop thread, only finish it) and such task is always blocking, so, yeah you need weak reference there
But it’s pretty different with coroutines, at least because coroutines are async and non-blocking