Membuat Database Room di Kotlin

Android 17 Mei 2021
Library Database

Membuat Database Room di Kotlin. Untuk menyimpan data pada Aplikasi Android, kita bisa juga menggunakan SharedPreference jika datanya sederhana. Namun bagaimana jika kita membutuhkan penyimpanan  local dengan data yang berelasi ? kita bisa menggunakan SQLite. Kita dapat merasakan kemudahan menggunakan SQLite dengan library Room. Room merupakan library bagian dari Android Jetpack yang dapat meningkatkan produktivitas dalam pengembangan aplikasi Android. Room adalah library yang dapat membuat akses database lebih mudah, namun tetap menggunakan kekuatan penuh dari SQLite. Berikut manfaat menggunakan Room sebagai berikut :

  • Query SQL dapat diverifikasi saat compile-time. Fitur ini akan memudahkan mengetahui kesalahan penulisan query saat aplikasi di compile.
  • Anotasi yang mudah untuk meminimalisir kesalahan.
  • Proses migrasi database yang mudah.

Komponen Utama Room

  • Database Class - Tempat mendeklarasikan Entitiy dan sebagai akses poin utama untuk koneksi ke data aplikasi.
  • Data Entities - Merepresentasikan tabel di database aplikasi.
  • Data Access Object (DAO) - Tempat menyediakan method SQL yang akan digunakan di aplikasi kita seperti Query, Insert, Update dan Delete data.

Latihan Membuat Database lokal dengan Room

Buat Project Android Studio, Pilih Empty Activity dan Masukkan konfigurasi seperti gambar di bawah.

  • Name: "RoomKotlin"
  • Package name: "com.teknorial.roomkotlin"
  • Language: Kotlin
  • Biarkan opsi lain sebagaimana adanya.
Konfigurasi Project

Setelah project selesai dikonfigurasi, kita akan menambahkan library ke dalam project Android. Buka build.gradle (Module: RoomKotlin.app) dan tambahkan terlebih dahulu id 'kotlin-kapt' kedalam plugins { }.

Kotlin-kapt digunakan untuk annotation processor yang diperlukan oleh anotasi dari room. Sekarang kita akan tambahkan library room masukkan kode bawah ke dalam dependencies{} dan kemudian tekan Sync Now setelah menambahkan library.

implementation 'androidx.room:room-runtime:2.3.0'
kapt 'androidx.room:room-compiler:2.3.0'
implementation 'androidx.room:room-ktx:2.3.0'

Setelah Gradle Sync selesai. Kita akan membuat tiga komponen utama dari room. Buat package baru bernama db.

Buat Package Baru

Pada folder package db,klik kanan->New-> Kotlin Class/File. buat data class baru bernama Book. Ini merupakan Entity atau tabel yang bernama Book di database.

Sekarang kita perlu mendefinisikan anotasi @Entitiy dan membuat beberapa nama kolom seperti kode di bawah.

package com.teknorial.roomkotlin.db

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Book(
    @ColumnInfo(name = "title") val title: String,
    @ColumnInfo(name = "author_name") val authorName: String,
    @ColumnInfo(name = "total_pages") val totalPages: Int
) {
    @PrimaryKey(autoGenerate = true)
    var id: Int? = null
}

Pada kode diatas kita telah membuat Entity bernama Book dan berisi kolom title, author_name, total_pages dan id yang auto generated.

Setelah membuat Entity atau tabel, kita akan membuat function query select, insert dan delete. Klik kanan pada folder db -> New -> Kotlin Class/File dan masukkan nama BookDao sebagai Interface.

Dalam interface BookDao kita akan membuat membuat query, insert dan delete. Modifikasi BookDao seperti kode di bawah.

package com.teknorial.roomkotlin.db

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query

@Dao
interface BookDao {
    @Query("SELECT * FROM book")
    fun getAllBooks():List

    @Insert
    fun insert(vararg books: Book)

    @Delete
    fun delete(book: Book)
}

Kita akan membuat Database Class untuk mendeklarasikan entity dan membuat versi dari database. Klik kanan pada folder -> New  -> Kotlin Class/File dan masukkan nama BookDatabase.

package com.teknorial.roomtutorial.db

import androidx.room.Database
import androidx.room.RoomDatabase

@Database(entities = [Book::class], version = 1)
abstract class BookDatabase: RoomDatabase() {
    abstract fun bookDao(): BookDao
}

Setelah tiga komponen Room ditambahkan. Kita akan mencoba memanggil database di MainActivity dan menggunakan beberapa function dari BookDao. Buka MainActivity dan modifikasi seperti kode di bawah.

package com.teknorial.roomkotlin

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import com.teknorial.roomkotlin.db.Book
import com.teknorial.roomkotlin.db.BookDatabase

class MainActivity : AppCompatActivity() {

    lateinit var db: BookDatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //inisialisasi Database
        db = Room.databaseBuilder(applicationContext, BookDatabase::class.java, "book-db").build()

        initData()

    }

    private fun initData() {
        val book1 = Book("Ada Apa dengan Hujan", "Andre Senja", 30)
        val book2 = Book("Malam setelah Sore", "Andi Bisa", 40)
        val book3 = Book("Pecahkan Mentari", "Dera", 20)
        //insert data ke database
        db.bookDao().insert(book1)
    }
}

Sekarang kita coba run aplikasi untuk menguji apakah Room dapat berjalan dengan baik tanpa error dengan kode di atas.

Setelah run aplikasi kita menemukan error Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time. Error tersebut terjadi karena kita memanggil database ke dalam main thread, itu dapat menyebabkan aplikasi menjadi freeze jika akses database terlalu lama. Untuk membuat akses database di luar main thread, kita bisa menggunakan Coroutine.

Coroutine adalah design pattern yang dapat kita gunakan di Android untuk menyederhanakan kode yang dieksekusi secara asinkron (Asynchronous). Di Android, Coroutine berguna untuk mengelola tugas yang berjalan lama seperti fungsi mengambil data dari server, mengupload gambar, dan bahkan digunakan untuk kalkulasi yang membutuhkan waktu lama.

Sekarang kita akan membuat akses database berjalan di luar main thread dengan menggunakan Coroutine. Pertama kita perlu menambah library coroutine di build.gradle (Module: RoomKotlin.app).

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'

Kembali ke MainActivity dan  kita akan memanggil function initData() di dalam GlobalScope.

package com.teknorial.roomkotlin

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import com.teknorial.roomkotlin.db.Book
import com.teknorial.roomkotlin.db.BookDatabase
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    lateinit var db: BookDatabase

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //inisialisasi Database
        db = Room.databaseBuilder(applicationContext, BookDatabase::class.java, "book-db").build()

        //menggunakan coroutine
        GlobalScope.launch {
            initData() //memanggil function di dalam coroutine

        }
    }

    private fun initData() {
        val book1 = Book("Ada Apa dengan Hujan", "Andre Senja", 30)
        val book2 = Book("Malam Setelah Sore", "Andi Bisa", 40)
        val book3 = Book("Pecahkan Mentari", "Dera", 20)
        //insert data ke database
        db.bookDao().insert(book1)
    }
}

Run aplikasi kembali dan kita akan melihat aplikasi tidak error seperti gambar di bawah.

Kita telah berhasil insert data namun kita belum menampilkan hasil ke dalam Aplikasi. Kita akan menggunakan TextView untuk menampilkan hasil Query. Buka activity_main.xml, tambahkan id ke dalam TextView.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Kembali ke MainActivity dan kita akan memanggil TextView untuk menampilkan data dari database.

package com.teknorial.roomkotlin

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import com.teknorial.roomkotlin.db.Book
import com.teknorial.roomkotlin.db.BookDatabase
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    lateinit var db: BookDatabase
    lateinit var tvDisplay: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //inisialisasi TextView
        tvDisplay = findViewById(R.id.tv_display)

        //inisialisasi Database
        db = Room.databaseBuilder(applicationContext, BookDatabase::class.java, "book-db").build()

        //menggunakan coroutine
        GlobalScope.launch {
            //memanggil function di dalam coroutine
            initData()
            diplayData()
        }
    }

    private fun diplayData() {
        val books: List = db.bookDao().getAllBooks()
        var displayText = ""
        for (book in books) {
            displayText += "${book.id} | ${book.title} | ${book.authorName} | Hal : ${book.totalPages}\n"
        }
        tvDisplay.text = displayText
    }

    private fun initData() {
        val book1 = Book("Ada Apa dengan Hujan", "Andre Senja", 30)
        val book2 = Book("Malam Setelah Sore", "Andi Bisa", 40)
        val book3 = Book("Pecahkan Mentari", "Dera", 20)
        //insert data ke database
        db.bookDao().insert(book1)
    }
}

Run App kembali dan kita akan melihat data book tampil seperti screenshot di bawah.

Query Select Room

Kita berhasil menampilkan book1 dan terlihat lebih dari satu data yang sama karena data di insert setiap menjalankan aplikasi. Kita akan membuat delete keseluruhan data Book  dan kemudian insert kembali  data book1, book2, book3. Buka BookDao kembali, tambahkan function deleteAll()  seperti kode di bawah.

package com.teknorial.roomkotlin.db

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query

@Dao
interface BookDao {
    @Query("SELECT * FROM book")
    fun getAllBooks():List

    @Insert
    fun insert(vararg books: Book)

    @Delete
    fun delete(book: Book)

    @Query("DELETE FROM book")
    fun deleteAll()
}

Kembali ke MainActivity. Kita akan memanggil  function deleteAll() sebelum initData() dan tambahkan insert data book1, book2, book3.

package com.teknorial.roomkotlin

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.room.Room
import com.teknorial.roomkotlin.db.Book
import com.teknorial.roomkotlin.db.BookDatabase
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    lateinit var db: BookDatabase
    lateinit var tvDisplay: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //inisialisasi TextView
        tvDisplay = findViewById(R.id.tv_display)

        //inisialisasi Database
        db = Room.databaseBuilder(applicationContext, BookDatabase::class.java, "book-db").build()

        //menggunakan coroutine
        GlobalScope.launch {
            //memanggil function di dalam coroutine
            db.bookDao().deleteAll() //<--
            initData()
            diplayData()
        }
    }

    private fun diplayData() {
        val books: List<Book> = db.bookDao().getAllBooks()
        var displayText = ""
        for (book in books) {
            displayText += "${book.title} | ${book.authorName} | Hal : ${book.totalPages}\n"
        }
        tvDisplay.text = displayText
    }

    private fun initData() {
        val book1 = Book("Ada Apa dengan Hujan", "Andre Senja", 30)
        val book2 = Book("Malam Setelah Sore", "Andi Bisa", 40)
        val book3 = Book("Pecahkan Mentari", "Dera", 20)
        //insert data ke database
        db.bookDao().insert(book1, book2, book3) //<--
    }
}

Run App kembali dan tiga data Book akan muncul seperti screenshot di bawah.

Kita berhasil menggunakan library Room dan menggunakan query select, insert, delete di database. Demikian tutorial Membuat Database Room di Kotlin. Silahkan komentar jika ada pertanyaan tentang tutorial in. Terima kasih telah membaca.

Source Code : https://github.com/rflash95/RoomKotlin

Tag