I have many snapshot states and I want to compute ...
# compose
a
I have many snapshot states and I want to compute a derived value from them, and show it, but the computation can take a while and while it’s running, I’d like to show a progress indicator. How do I arrange a State object whose value is
Computing
while the computation is in progress and
Result
when it’s done? The computation should happen on a background thread and preferably should restart when its dependencies change.
I want something similar to snapshotFlow, or derivedStateOf, but with the ability to indicate to the listener/observer when the computation has restarted.
and I don’t want to specify the keys myself manually, like e.g. produceState requires.
y
if you know the exact value that will be returned from that it would be easy
z
produceState
might be what you’re looking for
a
produceState is what I’m using right now, but it’s really cumbersome to have to specify all the keys manually.
z
@Chuck Jazdzewski [G] I think this might be a good use case for the
TaskEffect
you were telling me about?
c
Yes, this sound like a use case to me too. My primary issue with
produceState
is that it requires going though composition to restart. This means that, not only does it restart composition (which requires a rendezvous with the main thread), it is a frame behind as it doesn't restart the producer until after the next composition. This means that the results are often a frame or two late. Even if we would automatically calculate the keys, it wouldn't fix this issue, the value would still be late. Ideally, for a long running producer, the producer should restart independent of composition, and only trigger composition when a new value is produced. In JavaScript frameworks that use signals (such as Qwik) what you describe is referred to as a
Task
and the task produces a signal that is dependent on any signals that are read as part of producing the new value. The task is restarted whenever any of the dependent signals change. In Compose that would translate into a state where the producer for the state is run in a coroutine with a (readonly?) snapshot that tracks state reads. It would automatically reproduce the result if any of the states read change. If the values change during computation, the producer coroutine would (optionally?) be cancelled and restarted. A consistent producer would only produce a state if the states it read are unmodified (I am thinking a consistent producer would be the default as the failure to apply would be rare and if it does occur often a stale value would not be valid; handling potentially stale values would require planning for the consumer).
Task
is a bit of an overloaded term but this seems to describe what you want here.
a
Yes, that sounds right.
c
@Leland Richardson [G] and I discussed this briefly and we have some questions about your use case. First,
snasphotFlow()
seems to be able to most of what you want now. What about
snapshotFlow()
doesn't work in your scenario? I have some ideas but I want to make sure I am not just projecting my opinion on your use case. Second, does your case need to be on another thread or would a callback on the main thread be sufficient?
a
With snapshotFlow I have no way to indicate to the collector that the computation has restarted. Yes, I need to run the computation on a background thread, as it could take a few seconds.