Hey, I'm having issues with Context Receivers... I...
# getting-started
n
Hey, I'm having issues with Context Receivers... I have this code:
Copy code
context(ViewModel)
fun <T> Flow<T>.stateInViewModel(initialValue: T? = null): StateFlow<T?> = stateIn(
    this@stateInViewModel.viewModelScope,
    started = SharingStarted.WhileSubscribed(
        stopTimeoutMillis = 5_000,
        replayExpirationMillis = 0,
    ),
    initialValue = initialValue,
)
But
this@stateInViewModel
won't resolve to ViewModel, only to
Flow<T>
. I thought I could get the ViewModel instance with Context Receivers, but it doesn't seem like it. Why ?
Compiling
Copy code
context(ViewModel)
fun <T> Flow<T>.stateInViewModel(initialValue: T? = null): StateFlow<T?> {
    val viewModel: ViewModel = this@stateInViewModel

    return stateIn(
        viewModel.viewModelScope,
        started = SharingStarted.WhileSubscribed(
            stopTimeoutMillis = 5_000,
            replayExpirationMillis = 0,
        ),
        initialValue = initialValue,
    )
}
produces
Type mismatch: inferred type is Flow<T> but ViewModel was expected
e
why would you expect
this@stateInViewModel
to mean something other than the
Flow<T>
that is the receiver?
same as in any enclosing class,
this@ViewModel
for the context
n
If
this@stateInViewModel
cannot represent the
context
, then I have no idea of the purpose of
context
Documentation is lacking and the KEEP is just too much for me
e
this
always means exactly one thing.
context
allows name lookup to happen through multiple different scopes.
if
this@stateInViewModel
were
ViewModel
, how would you get a reference to the
Flow<T>
?
n
I thought this was exactly the magic behind
context
But I was obviously mistaken
t
I used it exactly to do this, I'm trying to find where's the code, but it worked fine
e
anyhow as I said, it's literally the same as
Copy code
class Foo {
    fun Bar.f() {
        flow {
            this // flow
            this@f // Bar
            this@Foo // Foo
context(Foo)
this@Foo
n
Oooooh
I'm dumb
Copy code
context(ViewModel)
fun <T> Flow<T>.stateInViewModel(initialValue: T? = null): StateFlow<T?> = stateIn(
    this@ViewModel.viewModelScope,
    started = SharingStarted.WhileSubscribed(
        stopTimeoutMillis = 5_000,
        replayExpirationMillis = 0,
    ),
    initialValue = initialValue,
)
Works
😄 1
e
the KEEP is also not that challenging to read
I expect more documentation when the feature leaves experimental status (so not for a few releases)
👍 1
n
Yes, this is to be expected for experimental features