hi devs,
i try to integrate coroutines with tornadofx, so i try to do some think like this
val View.viewScope get() = CoroutineScope(Dispatchers.Main)
with View class, i start coroutine when view is created (with init() method)
class myView : View() {
init() {
viewScope.launch { ..... }
viewScope.coroutineContext[Job]?.children?.forEach { println(it) }
}
// callback when view is dettached from scene
fun onUndock() {
viewScope.cancel()
}
}
so i expected see one child print , but i find some think confuse: there is no child in viewScope !!! why ??
if i understand, any coroutine launched in scope it will be a child of this scope
This val View.viewScope get() = CoroutineScope(Dispatchers.Main)
will create a new scope every time you launch something which is not good. Also since you create and forget viewScope
each time, you do not call cancel()
on it when your View
is disposed. You may inplement a weak referenced hashmap where the key is the view and the value the CoroutineScope
and “cache” it.
i not understand your reply
you say: viewScope is created and forget each time how that ???
why coroutine created in this scope is not a child ???
When using a custom getter for a field (the get() {}
) you are actually creating a function. That means that each time you call your viewScope
you are creating a new CoroutineScope
upon which you call a .launch {}
. After that the garbage collector picks up your newly generated viewScope
and deletes it!
The next time you invokeviewScope
it will be a completely separated, newly created CoroutineScope
!
You need to save it! To do so, you may extend View
into a custom view and let it implement CoroutineScope
and then subclass it.
This is probably easier to understand intuitively when you switch to kotlin from java.
var foo: Int
is the same as javas
private int foo;
public void setFoo(int value) {
foo = value;
}
public int getFoo() {
return foo;
}
And whenever you use foo
like in println(foo)
the java equivalent would be println(getFoo())
.
As @lamba92 said you can see that get() {}
generates a function if you look at the java equivalent:
val foo: Int
get() = TODO()
int getFoo() {
return TODO()
}
In this case the compiler also creates no backing field, because you calculate the value of foo
every time.