Skip to content

Commit

Permalink
Add links, fix typos
Browse files Browse the repository at this point in the history
  • Loading branch information
dturner committed Feb 14, 2024
1 parent 81f8e9b commit dd71bcf
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private val headingMarkdown = """
private val introMarkdown = """
By [Adetunji Dahunsi](https://twitter.com/Tunji_D).
State is what is. A declaration of things known at a certain point in time. As time passes however, state changes as data sources backing the state are updated and events happen. In mobile apps this presents a challenge; defining a convenient and concise means to produce state over time.
State is what it is. A declaration of things known at a certain point in time. As time passes however, state changes as data sources backing the state are updated and events happen. In mobile apps this presents a challenge; defining a convenient and concise means to produce state over time.
This page is a [Jetpack Compose](https://developer.android.com/jetpack/compose?gclid=Cj0KCQjwzqSWBhDPARIsAK38LY-nnY_1sTpVvpENJZD5ek-tE18e3MvzE1hXlILdw7uYx1Y47zsvcXkaAlGJEALw_wcB&gclsrc=aw.ds) for [web](https://compose-web.ui.pages.jetbrains.team/) powered interactive experiment that highlights various ways of producing state with a [Flow](https://kotlinlang.org/docs/flow.html). At the end of it, you should have a mental framework to help choose a state production pipeline that is most beneficial to your use cases.
Expand All @@ -79,8 +79,8 @@ Producing state is at its core, is nothing more than consolidating sources of ch
While the tenets of UDF are simple, there's a bit more to implementing it properly especially with `Flows`. Let's start simple. In the following we have a snail along a track. The snail has the following properties:
* It's progress along the track.
* It's color.
* Its progress along the track.
* Its color.
An easy way to represent the state production pipeline for the snail is with a single `MutableStateFlow`:
""".trimIndent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ To produce state then, we simply have to start with an initial state, and increm
Expressing this in code with `Flows` is very concise and requires just two operators:
* `merge`: Used to merge all sources of `Mutation<State>` (Δstate) into a single stream
* `scan`: Used to reduce the stream of `Mutation<State>` into the state being produced.
* [`merge`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/merge.html): Used to merge all sources of `Mutation<State>` (Δstate) into a single stream
* [`scan`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/scan.html): Used to reduce the stream of `Mutation<State>` into the state being produced.
In our snail example, we can express the same state production pipeline with user actions as:
""".trimIndent()
Expand Down Expand Up @@ -113,7 +113,7 @@ class Snail5StateHolder(
speedChanges,
changeEvents,
)
.scan(Snail5State()) { state, mutation -> mutation(state) }
.scan(Snail5State()) { startState, mutation -> mutation(startState) }
.stateIn(...)
fun setSnailColor(index: Int) {
Expand Down Expand Up @@ -150,7 +150,7 @@ It however brings the following advantages:
The switch to `MutableSharedFlow` from `MutableStateFlow` for propagating user actions is because `StateFlow` conflates emissions. If two separate methods attempted to use the same `MutableStateFlow` to emit a `Mutation` of state, the `StateFlow` may only emit the latest `Mutation`. That is `MutableStateFlow` does not guarantee that every update to its `value` property is seen by its collectors.
`MutableSharedFlow` on the other hand has an `emit` method which suspends until the `Mutation` is delivered. This means that multiple coroutines can be launched across several method invocations and call `emit` on the same `MutableShared` `Flow` and none of them will cancel out the other. The order in which they are applied also don't matter as `Mutation` instances just describe changes to state; they are designed to be independent.
`MutableSharedFlow` on the other hand has an `emit` method which suspends until the `Mutation` is delivered. This means that multiple coroutines can be launched across several method invocations and call `emit` on the same `MutableShared` `Flow` and none of them will cancel out the other. The order in which they are applied also doesn't matter as `Mutation` instances just describe changes to state; they are designed to be independent.
""".trimIndent()

Expand Down Expand Up @@ -193,7 +193,7 @@ Drag the snail to place it anywhere on its track. Also, try to hold it in place
private val nineMarkdown = """
That is, we can simply introduce a state change to the `progress` property of the state despite the `progessChanges` flow also contributing to a change of the same property. This is something that would be rather difficult with the `combine` approach. This is because the combine approach only lets you set state properties of state to create new state. The `merge` approach instead lets you `mutate` or change properties of state and apply them to the existing state.
Furthermore both `setSnailColor` and `setProgress` contribute their changes to state using the same `MutableSharedFlow`: `changeEvents`. This approach scales well because no mater how many methods are added that change the `State` from user events, they don't need any more variables to be declared in the state holder class.
Furthermore both `setSnailColor` and `setProgress` contribute their changes to state using the same `MutableSharedFlow`: `changeEvents`. This approach scales well because no matter how many methods are added that change the `State` from user events, they don't need any more variables to be declared in the state holder class.
""".trimIndent()

private val tenMarkdown = """
Expand Down

0 comments on commit dd71bcf

Please sign in to comment.