Strategi Sinkronisasi Data Online & Offline di Android Menggunakan NetworkBoundResource

Table of Contents

Building content...

Dalam pengembangan aplikasi mobile tentunya kita pernah diminta untuk mengembangkan aplikasi yang dapat berjalan dalam mode online atau offline. Terkadang pengguna bisa berpindah jaringan, kehilangan sinyal, atau berada di area dengan latensi tinggi.

Ada banyak cara yang dapat kita tawarkan untuk solusi agar aplikasi dapat berjalan dalam mode online atau offline. Salah satunya adalah NetworkBoundResource. Sebuah kelas dimana kita dapat mengatur strategi sinkronisasi data antara local data dengan data dari api.

Pendekatan ini adalah cara paling mudah di terapkan dan dapat di customize. Kita dapat mengatur proses apa saja yang mau kita terapkan seperti menambahkan authentication dan juga pagination.

Untuk tutorial kali ini saya akan spesifik untuk pengembangan aplikasi android dengan native kotlin. Dengan tema aplikasi Movie List menggunakan data dari API TMDB. Tentu saja NetworkBoundResource bisa di terapkan juga di iOS swift atau juga multiplatform dengan Flutter atau React.

Alur proses NetworkBoundResource

Penjelasan Singkat Alur

  1. Load data dari database UI selalu mengamati database (Room + Flow).
  2. Cek perlu fetch atau tidak Biasanya berdasarkan:
    • Data null
    • Data kosong
    • Expired (TTL)
    • Force refresh
  3. Jika perlu fetch
    • Panggil API
    • Simpan ke database
    • Database otomatis emit ulang data terbaru
  4. Jika tidak perlu
    • Langsung emit data lokal
    • Tidak ada network call

Penjelasan Mengenai TTL

TTL (Time To Live) adalah durasi validitas data yang disimpan secara lokal (misalnya di database atau cache). Selama periode TTL belum terlampaui, data dianggap masih valid dan dapat digunakan tanpa perlu melakukan request ulang ke server.

Jika TTL sudah expired, maka data dianggap kadaluwarsa sehingga aplikasi perlu melakukan sinkronisasi ulang (ke server untuk mendapatkan data terbaru.

Teknologi yang Digunakan

Dalam implementasi sinkronisasi data online dan offline, berikut adalah stack teknologi yang digunakan:

  1. Room Database Digunakan sebagai local database untuk menyimpan data yang dapat diakses saat aplikasi dalam kondisi offline.
  2. Retrofit + OkHttp Digunakan untuk komunikasi dengan REST API.
    • Retrofit berfungsi sebagai HTTP client abstraction untuk mendefinisikan endpoint API.
    • OkHttp menangani koneksi jaringan, logging, interceptor, dan konfigurasi timeout.
  3. Gson Digunakan untuk parsing JSON response dari API menjadi object Kotlin (DTO).
  4. Koin Digunakan sebagai dependency injection untuk penyediaan dependency seperti Repository, ViewModel, Database, dan Network layer.
  5. Kotlin Coroutines Digunakan untuk menangani asynchronous operation secara non-blocking, terutama untuk operasi database dan network call.
  6. Glide Digunakan untuk image loading dan caching.
  7. Chucker Digunakan untuk monitoring dan debugging HTTP request/response selama proses development.
  8. MVVM (Model-View-ViewModel) Digunakan sebagai arsitektur untuk memisahkan business logic, data layer, dan UI layer sehingga aplikasi lebih modular, maintainable, dan testable.

Membuat class Network Bound Resource

Penjelasan Setiap Tahapan

1. query()

  • Mengambil data dari Room
  • Atau anda bisa lakukan proses lain seperti validasi data, men-generate kode uniq dsb.

2. shouldFetch(data)

Menentukan apakah perlu call API:

Contoh kondisi:

  • data null
  • data kosong
  • data expired (TTL)
  • force refresh

3. createCall()

  • Melakukan proses call API untuk sinkronisasi data API

4. saveCallResult(response)

  • Mapping DTO → Entity
  • Simpan ke database

5. Emit State

Kita akan menggunakan sealed class sebagai state pada proses di NetworkBoundResource.

Apa Itu Sealed Class?

Sealed class adalah jenis class tertutup di Kotlin yang tidak bisa diwariskan secara bebas di mana saja. Hanya bisa memiliki turunan yang sudah ditentukan. Berbeda dengan open class yang bisa diwariskan oleh class mana pun.

Membuat Service API

Saya akan mengambil data dari api TMDB.

Endpoint yang di gunakan:

GET:

https://api.themoviedb.org/3/movie/popular

Response:

GET:

https://image.tmdb.org/t/p/w185

Di gunakan untuk mendapatkan data gambar. w185 adalah ukuran gambar yang di dapat. Anda dapat mengganti ukuran gambar sesuai dengan kebutuhan. Lalu gabungkan endpoint ini dengan data poster_path yang nantinya kita pakai pada Glide.

Saya Menyimpan ke 2 endpoint tersebut ke dalam class Configs berserta message error dan pengaturan timeout.

Membuat class MovieService:

Membuat data class MovieModel:

Saya menambahkan function untuk mapping data MovieModel ke MovieEntity untuk dapat di simpan ke local database.

Membuat data class MovieEntity:

Saya menambahkan fungsi getPosterUrl() sebagai data endpoint untuk ambil gambar.

Membuat class Dao:

Membuat class TypeConverter:

Class ini di gunakan untuk mengkonversi data list genre id untuk di jadikan string saat ingin di simpan ke table movie dan akan di konversi ulang menjadi list genre id saat kita select datanya.

Membuat class LocalDatabase:

Membuat Class Repository:

Di sini lah NetworkBoundResource kita gunakan sebagai layer dari proses ambil data ke local database dan proses sinkronisasi ke API.

Membuat class ViewModel:

Dalam class MainViewModel saya menginisiasi getMovieList() menggunakan flatMapLatest agar flow lama dibatalkan otomatis, tidak ada api bertumpuk, aman untuk refresh berulang dan membuat fungsi refresh dengan StateFlow.

Sebelumnya saya tidak menggunakan flatMapLatest untuk memproses data dari getMovieList. Saya langsung membuat fungsi yang sama di viewModel lalu di jadikan LiveData agar bisa di observe di UI. Jika saya mau melakukan refresh data saya akan panggil ulang fungsi tersebut alhasil flow lama masih tetap aktif sementara flow baru dibuat. Akibatnya, pemanggilan API terjadi berulang (multiple request).

Selain itu, jika di dalam flow tersebut terdapat pemanggilan fungsi lain, maka fungsi tersebut juga akan ikut terpanggil berulang kali karena kedua flow berjalan secara bersamaan.

Koin Modules

Saya membagi jadi 3 module. Module remote, local dan domain.

  • Module remote : Untuk inisiasi retrofit, okHttp, chunker dll
  • Module local : Untuk inisiasi Room Dabase
  • Module domain : Untuk inisiasi repository dan viewModel

Module Remote

Module Local

Module Domain

Jangan lupa buat class Application dan inisiasi semua koin module di dalamnya.

Implementasi Pada UI

Untuk refresh Anda tinggal panggil saja fungsi refresh yang sudah di buat di viewmodel.

Sejak Android versi 13, aplikasi wajib meminta runtime permission untuk menampilkan notifikasi. Untuk itu kita perlu meminta permission untuk notifikasi karna kalau tidak chunker tidak akan muncul pada jendela notifikasi.

Hasilnya

Mulailah dengan kondisi online untuk mendapatkan data awal. Kemudian Anda dapat mematikan mode jaringan pada device Anda untuk mencoba mode offline. Anda bisa melakukan refresh data atau menutup aplikasi lalu memulai lagi. Anda akan melihat saat mode offline aplikasi tetap menampilkan data.

Penutup

Strategi sinkronisasi online dan offline bukan hanya soal teknis, tetapi soal memastikan aplikasi tetap bisa digunakan kapan pun dan di mana pun. Dengan pendekatan seperti NetworkBoundResource, kita bisa menghadirkan pengalaman yang lebih stabil dan nyaman bagi pengguna, meskipun kondisi internet dalam keadaan buruk.

Tentunya selain proses pengambilan data. Aplikasi juga perlu untuk bisa melakukan pengolahan data seperti transaksi yang dapat berjalan juga di mode offline agar user yang menggunakan aplikasi kita tetap bisa melakukan aktivitasnya tanpa terganggu jaringan. Yang nantinya dapat di sinkronkan data yang di simpan di local ke server.

LOGIQUE membantu bisnis Anda tumbuh melalui transformasi digital yang terarah. Kami menyediakan layanan konsultasi IT, pengembangan website, pengembangan aplikasi web dan mobile, pengembangan sistem, serta layanan pemasaran digital.

JAGAWEB BY LOGIQUE

Solusi all-in-one untuk Keamanan dan Operasional Website

JagaWeb dirancang untuk bisnis yang membutuhkan performa website yang stabil, aman, dan terus berkembang tanpa perlu mengelola banyak vendor sekaligus.

PENTEST CHECKUP BY ETHICAL HACKER

Pentest untuk Mendeteksi Risiko Keamanan Sejak Dini

Layanan pemeriksaan keamanan cepat oleh OSCP-certified pentester, dirancang untuk mengidentifikasi risiko nyata dan memberikan rekomendasi perbaikan yang jelas.