Offline First Application
Long time no see guys. Today I want to write about how I write an Android application that can be used in offline mode but still need to store data in server when internet connection is available.
The example use case is Point of Sales app. This kind of application is used by cashier to record the transactions happened in offline store. The application has to work even when there are no internet connection available because customer is not expected to wait too long.
What is the scenario?
- When creating order and transaction, we have to assume no internet connection is available so we need to store the order and transaction data in local storage first.
- After the order and transaction data are saved into local storage, then we can sync the data to our backend (if needed) immediately using background worker so it doesn't affect UI because cashier may have another customers to serve.
- When step number 2 is failed we can set the worker to retry using exponential backoff so it won't affect backend too much when backend is having problems and already up again.
- Last backup, we have scheduled worker that checks if there are unsynced transactions every xx hours.
How can we achieve this?
Code-wise, we'll divide the thing into two layers.
- Data layer. In this layer, we define how data is saved into SQLite DB.
- Domain / Use Case. In this layer, we define the business use case that may depends on several queries on data layer. Several examples:
Offline Storage - Data Layer
Firstly, we need to decide which offline storage solution that we want to use. Android app can use default SQL based solution provided by SQLite as the local storage. In this use case, we decide to use SQLite because order and transaction data is structured so it's easier to use SQL based solution which is SQLite.
In this use case, we define that we need to store data in two tables: orders
and transactions
.
- Order data
- order id or order number
- created at timestamp
- order items
- order status
- Transactions data include
- transaction id
- order id
- paid amount
- payment type
- paid at timestamp
Background Worker - Data Layer
There are some libraries we can use to create a worker, but now I will just provide how to define the worker suited in our use cases.
We need to define some worker to sync our data:
- Sync order worker
- Order id is provided
- Worker will query to local database to get the order data based on order id
- Format it into JSON
- Sync JSON formatted data into backend
- Flag it to
synced
so it doesn't need to be synced again.
- Sync transaction worker
- Transaction id is provided
- Worker will query to local database to get the transaction data based on transaction id
- Format it into JSON
- Sync JSON formatted data into backend
- Flag it to
synced
so it doesn't need to be synced again.
- Scheduled data sync worker.
- Every
xx
hours the worker will check if there are unsynced order and transaction data - Format it into JSON
- Sync JSON formatted data into backend
- Flag it to
synced
so it doesn't need to be synced again.
- Every
Use Cases / Domain Layer
We can compose a business use case using several data layer functions. Some examples:
- Create pending order
- Create a row in
orders
table withpending
status - Sync pending order data into backend using
order worker
- Create a row in
- Save paid order
- Update order status from
pending
intofulfilled
- Sync fulfilled order data into backend using
sync order worker
- Create a row in
transactions
table withpaid
status with relatedorder id
inorders
table. - Sync paid transaction data into backend using
sync transaction worker
- Update order status from
That's my idea about how we can achieve the *offline first application`. I will write some code examples in my next post. See you 😃