Hello, My composable accepts a state object (`Some...
# compose
d
Hello, My composable accepts a state object (
SomeState
) that needs to be explicitly closed (
SomeState.close()
) to be cleaned up when it is no longer in use. To simplify the creation of the state object for users, I implemented a
rememberSomeState
function, which not only creates and remembers the state but also handles the resource cleanup by adding a
DisposableEffect
to close the state when
rememberSomeState
leaves the composition:
Copy code
@Composable
fun rememberSomeState(value: SomeValue): SomeState {
    val state = remember(value) {
        SomeState(value)
    }
    DisposableEffect(value) {
        onDispose {
            state.close()
        }
    }
    return state
}
My question is: How natural would this approach be in the Compose world? I’ve typically seen
rememberSomething
functions used for managing state that doesn’t need explicit resource management (e.g., objects that don’t require closing or cleanup). I’m wondering if embedding
DisposableEffect
within a
rememberSomething
function is an accepted pattern, or if it's better to leave the cleanup responsibility to the caller of the composable. Any insights or guidance would be greatly appreciated.
z
What you're doing is fine, it's a pattern used even in the compose codebase. One note: the key to
DisposableEffect
could be
state
instead of
value
, which is technically more precise since it's
state
that's captured by the effect but what you're doing should have the same effect since the same key is used for remembering the state anyway.
👍 1
h
z
It's dangerous to make the thing you're returning implement
RememberObserver
, since it can be remembered by code outside your control. If you have a private object that you're remembering and returning a different object, then it is ok. E.g. In the OP snippet, making
SomeState
implement
RememberObserver
would be bad. But if it returned
state.actualState
and
actualState
didn't implement RO, that would be ok.
d
thanks a lot
a
One neat anonymous object trick to avoid the issue with a
RememberObserver
being remembered by something else, you could do:
Copy code
@Composable
fun rememberSomeState(value: SomeValue): SomeState =
    remember(value) {
        object : RememberObserver {
            val state = SomeState(value)
            override fun onAbandoned() = onForgotten()
            override fun onForgotten() {
                state.close()
            }
            override fun onRemembered() = Unit
        }
    }.state