Jetpack Compose + MVI - Part 1: Side Effects
Tags: android, kotlin, tutorial
Published: 2023-05-24 12:30:00

Previously, I had introduced the mechanics of a **MVI + Redux** Design Pattern and implemented it as an example.

{% embed https://dev-to-uploads.s3.amazonaws.com/uploads/articles/the4sjvlkqtllfl328u0.gif %}

The UI is DaVinci-esque ¬‿¬ but has one problem: **Button does nothing**.

We would make the click of Button to emulate a REST API Response. This would mean that UI should show progress or some indicator that operation is ongoing.

To emulate a REST API Call, we need a Repository:

{% embed https://gist.github.com/ritwikjamuar/b59cb17283bdbd26c9866953f13a56a1 %}

`fetchSomething()` provides a `Boolean` flag that indicates whether fetching was success or not.

Now, since performing REST API Call is considered side-effect, we create a `MiddleWare` to handle such side-effect, and here comes `ExampleMiddleWare`.

## Enter `MiddleWare`

To recap, the purpose of `MiddleWare` is to handle side-effects (or `Action` that does not make sense to a `Reducer`). MiddleWare uses store to propagate another Action, whose processing is upto `Reducer` or another `MiddleWare` in the `Store`.

But before we start shaping the `MiddleWare` for our example, we must add actions that triggers the execution of this `MiddleWare` and prompts to change the state once the MiddleWare is finished. 

This means adding some actions in already existing `ExampleAction`:

{% embed https://gist.github.com/ritwikjamuar/3b1b355e5c089cfa72aa90cbf0c8ded5 %}

Now, we implement our `MiddleWare` as below:

{% embed https://gist.github.com/ritwikjamuar/b3b4e09b6fa23f665bb22ce858abe5e7 %}

Take a look at the method `onButtonClicked()`.

Whenever we receive an intent that Button is clicked, we perform REST API Call.

To make user aware of such, we propagate an action to Show Loading, and when the value is collected, we propagate an action to Hide Loading.

In order for our `MiddleWare` to work, we must incorporate it to `Store` in the MVIViewModel:

{% embed https://gist.github.com/ritwikjamuar/60de4dee8df54d64a3da11b286b7afb0 %}

Because we wish to update our UI whenever Showing or Hiding progress is propagated, we add a field in our `State` to support that.

{% embed https://gist.github.com/ritwikjamuar/5ba182486b3c3d5bf5a871b57ae9a0f0 %}

Next, we update our `Reducer` to accommodate for new `Action`s, i.e. showing and hiding Progress

{% embed https://gist.github.com/ritwikjamuar/ceef1455fb5643ef659c9efd47b72b1b %}

## Back to UI

So, we add a Progress Bar to our screen using [`LinearProgressIndicator`](https://developer.android.com/reference/com/google/android/material/progressindicator/LinearProgressIndicator). To add some animating effect, wrapped the `LinearProgressIndicator` under [`AnimatedVisibility`](https://developer.android.com/jetpack/compose/animation/composables-modifiers#animatedvisibility).

{% embed https://gist.github.com/ritwikjamuar/3333ed52ea800fa02d8a94167ab419d0 %}

This results in our UI to look like this:

{% embed https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qf7fstn1op1s54l6ymqs.gif %}

## Side-Effects revisited

Above is one demonstration of handling REST API Call as side-effect.

But remember, **`MiddleWare` does not have to propagate any action**.

Here are some examples that does not propagate anything:

#### 1 : Logging

We want to log our Action and State of our Store for logging and debugging purposes. Logging is again another use case of side-effect, which then translates to `MiddleWare` as below:

{% embed https://gist.github.com/ritwikjamuar/56b81afa177b28264aabb3aa24f4f56d %}

This `MiddleWare` is general-purpose in nature and can be used with any `Store`.

#### 2 : Navigation

Navigating to another `Activity`/`Fragment` can also be thought of as a side-effect, which can be translated to a `MiddleWare` as below:

{% embed https://gist.github.com/ritwikjamuar/2059c23b3ea03097e6fd74e0dc438830 %}

The lambda `onNavigate` is handled by consumer for them to figure out on what action and state they perform navigation.

## Takeaways

The point is, **`MiddleWare` can be thought of as a silo that is designed for a singular or a set of purpose**.

Meanwhile `Reducer` has one role and one role only: **For a given `Action` that is considered state changing, `Reducer` reduces current `State` to a new one**.

Next post, will be a discussion around Testing.

Thank You!