Simple way to manage state in Kotlin

Tram Ho

Introduce

Before getting into the actual concepts, let’s first understand the problem we are going to deal with. State management is one of the important aspects of any platform when it comes to product development.

Let’s say you have a payment screen with multiple payment gateways: visa, momo wallet, zalo pay . Users can make payments using any gateway. After payment, there will be a confirmation pop-up indicating the status of the purchase.

This problem seems simple but it gets more and more complicated over time with many gates having many states. This is already solved by sealed classes .

However, not all problems are of equal complexity, a simple network request can have only two states such as success or failure. That’s when we need a simpler solution, preferably something that’s already in the language itself. That is what we will learn in this article.

Pick up the skirt:

Problem: Find a simple solution to manage state without creating new modules

Solution: Use runCatching and its capabilities with the Result sealed class in the standard Kotlin library.

Prerequisites

Before going any further, I strongly recommend that you have a bit of knowledge about sealed classes and coroutines. The problems and solutions in this article are based on them. If you don’t know from the beginning, you can refer to these 2 articles or any other online article:

Going back to the original problem,

Now, let’s see a simple example of how to use sealed classes. This is an example to maintain states when a network request is initiated. Here there are two states: Loading and Error.

Loading : This state returns a boolean if loading actually occurred – otherwise, it is hidden.

Error : This status returns an error message in the form of a string. When the error is triggered, the loading will be hidden and a popup with the error message will appear.

Now, on the other side, we have to use when statement in Kotlin to handle different states:

Of course, sometimes it’s even more complicated:

That’s how we will handle the above troublesome payment cases. Of course, large projects will, but for small projects, creating through so many things is not necessary when we already have the following:

Result & runCatching

Before diving into the solution to the problem above, let’s take a moment and learn about what we’re up to here.

Result

Result is nothing but a generic sealed class that we usually create in our projects to maintain state. But Result comes with the standard set of libraries, which means we don’t need to write our own custom classes, very convenient isn’t it! No need to add anything to taste. Don’t invent the wheel when we can use it already. If you want to dig into Result, click here . It basically serves as a sealed class by providing onSuccess and onFailure callbacks.

runCatching

runCatching calls the specified function block and returns its encapsulated result if the call succeeds, catches any Throwable exceptions thrown from execution and encapsulates it as a failure . See the following example:

Solution

Now that we have the handy functions in place, it’s time to put them to work. Our problem is to make a network request with simple state management using Result and runCatching .

We know that runCatching takes a Kotlin function as input and returns its result in Result format based on its success status. In our case a network request. Watch:

Looks simple, no try/catch for error handling, no manual state management custom classes. runCatching and Result provides more than a simple solution, which you will learn in the next section.

Extra Benefits

fold

One of the best things about using Result is using fold inline function , which encapsulates sucess and failure as parameters and gives us a chance to have a consistent return type. See the other code execution version in the solution section:

recover

recover allows you to handle the error and recover from it with a fallback of the same data type. See the following example.

Apart from these, there are some more interesting and handy functions like map , mapCatching , getOrDefault , getOrElse and more. You can refer all about them from here .

runCatching as an extension function

The runCatching function is capable of acting as a generic extension along with the normal inline function. Take a look at the syntax:

With this capability, we can directly call runCatching on request without having to do it individually:

This article is translated from https://medium.com/android-dev-hacks/simple-state-management-in-kotlin-6d1d5e41e4e8 . Hope everyone enjoys

Thank you!

Share the news now

Source : Viblo