Belajar Room DB (MVVM, Coroutines, LiveData)

Andi Wijaya
4 min readMay 11, 2020

--

Photo by Campaign Creators on Unsplash

Bagi kalian yang mampir ke tulisan ini mungkin sudah pernah menggunakan database SQLite dan ingin mengetahui bahkan mencoba sebuah library penyimpanan lain yang jauh lebih simpel dibandingkan SQLite, yaitu Room.

Room merupakan bagian dari Android Jetpack, dimana Jetpack merupakan kumpulan library, tools, dan architecture yang dapat membantu kalian mengembangkan aplikasi relatif lebih mudah dan cepat.

Tutorial ini akan mencakup penggunaan Room dengan arsitektur MVVM, LiveData, menggunakan bahasa Kotlin serta memanfaatkan Kotlin Coroutines.

Kita akan mencoba untuk menerapkan Room dengan membuat sebuah aplikasi Note dengan mockup seperti gambar di bawah ini

Pada project ini kita perlu menambahkan beberapa library pada build.gradle dan memastikan telah apply kedua plugin di bawah ini:

apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'

Tambahkan library berikut:

// RecyclerView
implementation "androidx.recyclerview:recyclerview:1.1.0"

// coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"

// Room
implementation "androidx.room:room-runtime:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"

// ViewModel
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
kapt "androidx.lifecycle:lifecycle-compiler:2.2.0"

Pastikan project kamu menggunakan AndroidX.

Komponen-Komponen Room

Kita mulai dari komponen-komponen yang dibutuhkan ketika menggunakan Room sebagai database kita

  • Database merupakan class yang menjadi tempat pendefinisian dan titik akses untuk terhubung dengan database yang kita gunakan.
AppDatabase.kt

Database selalu diberi anotasi @Database yang menandakan kelas tersebut merupakan kelas database. Anotasi ini menerima parameter daftar entity, export schema, dan versi database. Kelas ini didefinisikan sebagai sebuah kelas abstract yang mewarisi kelas RoomDatabase.

Isi dari kelas ini adalah kumpulan fungsi abstrak untuk masing-masing kelas Dao yang kita miliki dan mengembalikan kelas Dao tersebut.

Terdapat juga sebuah fungsi yang mengembalikan instance dari kelas database yang kita buat. Dari instance tersebut, kita dapat mendefinisikan kelas dan nama database yang akan kita gunakan.

Room.databaseBuilder(context, YourDatabaseClass::clas.java, "YOUR DATABASE NAME").build()
  • Entity, merupakan class yang merepresentasikan tabel dalam database dimana terdiri dari variabel yang merepresentasikan kolom dalam tabel
Note.kt

Anotasi @Entity dibutuhkan untuk mendefinisikan sebuah kelas adalah sebuah entity atau tabel dalam database. Anotasi ini menerima parameter tableName yang mendefinisikan nama dari tabel tersebut.

Seperti database relational pada SQLite, kita membutuhkan sebuah primary key sebagai kode unik dari sebuah record yang kita miliki di dalam tabel. Kolom yang didefinisikan sebagai primary key membutuhkan anotasi @PrimaryKey dan memiliki satu parameter autoGenerate dengan nilai false. Jika kita memberi nilai true pada autoGenerate maka setiap row baru akan diberi nilai increment dari nilai row terakhir.

@ColumInfo dibutuhkan untuk mendefinisikan nama dari kolom yang kita buat. Jika tidak diberi anotasi tersebut, maka nama tabel akan mengikuti nama variabelnya.

  • Dao merupakan interface yang digunakan untuk mengakses database
NoteDao.kt

Room menyediakan Data Manipulation default seperti CREATE dengan anotasi @Insert, UPDATE dengan anotasi @Update, DELETE dengan anotasi @Delete, dan anotasi @Query untuk membuat raw query sql.

Terlihat pada fungsi getNotes mengembalikan List berupa LiveData, dimana LiveData merupakan observable class holder yang memiliki kelebihan untuk memberikan pemberitahuan ke UI secara langsung jika terjadi sebuah perbuahan data, baik itu penambahan, perbaruan, ataupun penghapusan data.

Pada fungsi insert, delete, dan update merupakan proses I/O yang dapat memakan resource device pengguna. Proses ini memungkinkan terjadinya blocking, sehingga jika kita eksekusi dengan pemrosesan UI yang berada di Main Thread, akan terjadi hang atau device menjadi lambat.

Oleh karena itu, kita dapat mengunakan Kotlin Coroutines untuk menghindari blocking pada main thread. Seperti yang kalian lihat di NoteDao.kt, fungsi insert, delete, dan update diberi modifier suspend. Fungsi dengan tipe modifier ini hanya bisa dieksekusi oleh fungsi suspend lainnya atau dengan coroutines.

Setelah membuat 3 komponen utama dari Room, kita membutuhkan sebuah kelas untuk menghubungkan ViewModel dan database Dao. Kelas ini disebut kelas Repository, pada tutorial ini kita beri nama NoteRepository.kt

NoteRepository.kt

Seperti yang kalian liat pada fungsi insert, update, delete, kita mengakses fungsi dari kelas Dao. Fungsi tersebut mengharapkan eksekusi dengan coroutines setelah kita memberi modifier suspend, oleh karena itu, kita hanya bisa mengekekskusi fungsi tersebut dengan corutines.

launch(Dispatchers.IO) {     ...
...
}

Terdapat 3 macam Dispatcher yang disediakan untuk membedakan proses yang kalian lakukan dengan coroutines. Pada kasus ini, kita akan melakukan proses read and write database, dengan begitu kita gunakan Dispatchers.IO. Untuk penggunaan lebih mengenai coroutines, bisa baca di artikel ini.

Selanjutnya kita buat sebuah kelas ViewModel untuk mengatur alur data yang tampil pada UI atau tampilan aplikasi yang kita buat.

Setelah itu kita dapat menghubungkan ViewModel dengan Activity dengan menginisialisasi variabel dengan ViewModelProvider yang merujuk pada ViewModel yang ingin kita gunakan.

private lateinit var noteViewModel: NoteViewModel...
...
...
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)

Karena kita menggunakan LiveData maka kita dapat mengambil data melalui ViewModel dengan observer.

noteViewModel.getNotes()?.observe(this, Observer {
noteAdapter
.setNotes(it)
})

Kode diatas membuat fungsi getNotes yang mengembalikan List<Note> selalu diupdate secara otomatis setiap terdapat perubahan, dengan kata lain setiap ada data yang berubah fungsi setNotes pada adapter akan selalu dieksekusi.

Dengan demikian kita tidak perlu lagi refresh atau membuat kode untuk reload atau menarik data ulang dari database, ini karena pekerjaan tersebut telah dilakukan oleh ViewModel dan LiveData.

Karena tutorial ini tidak menjelaskan pembuatan UI dan lebih menjelaskan penggunaan Room, arsitektur MVVM, Coroutines, dan LiveData, maka implementasi UI dapat dicek pada repo yang di bawah ini.

--

--

Andi Wijaya

Community Enthusiast | Building banking app with Accenture