Redux for Android with Kotlin in practice, Part 2: Fetching data from network

Alla Dubovska
xorum.io
Published in
3 min readSep 30, 2019

In the first part of this series we’ve covered the initial setup of Redux architecture in Codeforces Watcher. This is an open-source Android application dedicated to users of quite famous platform for competitive programming — Codeforces. There are hundreds of contests each week with thousands of participants. Tasks are varied from quite basic to really advanced.

For now Codeforces Watcher allows users to see upcoming contests and track the activity of chosen users on the platform. We were about to add a few new features, but to make it easier, we decided to apply the right pattern first.

Executable actions

Commit: Add Request action.

In previous article, we’ve stopped by putting fetched contests into State. We did the network operation right in our View (ContestsFragment), which is obviously the wrong way in any architecture :) But how to do it properly with Redux?

The very first idea is to put network logic into Reducers as this is the only place where we can change our “immutable” State. But after trying this you’ll quickly find out that it’s not possible, because Reducers are executed on UI Thread and should return updated state as a result of call, no callbacks possible.

Instead we need to introduce special type of ActionRequest. This class introduces very simple idea of executable action:

abstract class Request : Action {

abstract fun execute()
}

Of course, here it could be just an interface, but by looking into the future, we’ve decided to make it an abstract class to be able to easily add some basic code when needed (handle coroutines, for example).

Anyway, it won’t work like that — we need to call execute somehow. Here Middleware comes to rescue:

val appMiddleware: Middleware<StateType> = { _, _ ->    { next ->        { action ->            (action as? Request)?.execute()

next(action)
}
}
}

But this won’t work either, because we need to say our Store to use appMiddleware, just like this:

val store = Store(
reducer = ::appReducer,
state = AppState(),
middleware = listOf(appMiddleware)
)

Fetching data from the network

Commit: Implement FetchContests request.

Let’s now move our old updateContestList method from ContestsFragment to brand-new FetchContests request (action, really). Overall, we just moving all the code to execute method, commenting our / removing some unrelated (for this commit) code.

NB: Outer class ContestsRequests isn’t critically important, but rather nice to have for separating feature scope.

To deliver result of Request, we need another simple Actions, which are usually called Success and Failure. These are data classes with fetched data / error depending on actual result of Request.

Then we can easily catch and handle them in contestsReducer:To be continued…

In this article we’ve seen how to properly fetch data from network and save it to state. As a result we have still working application, which is much closer to Redux architecture than it was just a few commits earlier.

In the next article we will try to handle loading state and show only Upcoming contests (because right now, all contests are shown — ooups 🙂)

--

--

Alla Dubovska
xorum.io

Software engineer (👩‍💻 native iOS development), Mom 👦, Marathon finisher 🏃🏻‍♀️