Redux is a pattern and library for managing and updating application state, using events called "actions". It serves as a centralized store for state that needs to be used across your entire application, with rules ensuring that the state can only be updated in a predictable fashion.
- Single source of truth ( Store )
- State is read-only ( State )
- Changes are made with pure functions ( Reducers )
According to the Redux principles we will create three components but with slight variation. For state update callback we will use MutableLiveData an AndroidX lifecycle component which allows us to observe the change in the data.
What are LiveData and Observers?
Observers are the functions which observe the changes in the LiveData and get automatically called when it receives any updates.
LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
*We are using Kotlin to show code examples.*
A state contains data that is accessible throughout the App. Here we are creating a To Do App for our sample project, so we will be storing the list of tasks in the App State. To make our todo list observable we will wrap it with LiveData, similarly you can wrap any type of class with LiveData and make it observable. Moreover you can add as many as variables using LiveData.
Reducer contains the logical part, in this class we will create functions to apply CRUD operations. Here we are using a different approach with respect to the Redux principles, we are creating separate functions for different actions instead of action-dispatch functions. You can not modify LiveData directly, so first we will cast it to MutableLiveData and then apply changes. For more details about MutableLiveData read official documentation here.
Store is a global object which contains the AppState and the Reducer. We will create our Store class with AppState and Reducer, Initialise AppState with initial state and pass the initial state to the reducer.
Ok! But how to combine these things together?
The Store should be accessible throughout the application, so we will need to create a global instance of store. Consequently we will extend the Application class and create a companion object, which will allow us to access the store object App wide.Don’t forget to add ThisApp to AndroidManifest.xml
To modify the App State we need to call reducer functions which we created earlier. Below is the code which shows how to call reducer functions.
Updating the UI
For our To Do App, we require to list the tasks in the recycler view, so we will create an Adapter for it. We will use our tasks array list as a data source for TaskAdapter.
But there is a problem, the TaskAdapter doesn’t know that the data has been changed, so we need to notify it about that. For this purpose we will add an observer for the tasks list in our activity as shown below,
Whenever the list gets updated, it will call taskAdapter.notifyDataSetChanged() which will update the recycler view.
Yesss ! we made it. That's how we can apply the Redux approach in Android using LiveData.
You can clone the sample project from github.
This approach might not suit all types of projects, in the end it depends on you to choose appropriate architecture as per your project requirements. The LiveData which we used is a part of MVVM architecture recommended by the Android officials.