Android Room API

The Room persistence library provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite.

Android Room API

Android Room API

kotlin + androidx + room api

Download sample app: https://github.com/datanapps/AndroidRoomAPI

Preview : https://www.youtube.com/watch?v=hOvG8Q208_I

To convert android project into androidx we have to follow below steps.

1. Need to add below line in gradle.properties

android.useAndroidX=true

android.enableJetifier=true

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

android.useAndroidX=true
android.enableJetifier=true

2. Add androidx dependencies in gradle file.

dependencies {
// app compact
implementation "androidx.appcompat:appcompat:1.1.0-alpha04"

// constraint layout
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

// recycle view
implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha04'

// ROOM API
implementation "androidx.room:room-runtime:2.0.0"
kapt "androidx.room:room-compiler:2.0.0"

// Run programm in background
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
}

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

 

Creating a sample Project in android studio

1. Create a sample project from android studio. to create a sample project please go to below steps:

File  >> New  >> New Project >> A popup will come then select a empty activity.

2. Open project app >> res >> change resource values file like strings, color, dimens.

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="colorGrey">#A6A6A6</color>

    <color name="colorBackTransparent_40">#A6FFFFFF</color>

</resources>

strings.xml

<resources>
    <string name="app_name">RoomAPI</string>
    <string name="action_settings">Settings</string>
</resources>

styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

</resources>

dimens.xml

<resources>
    <dimen name="fab_margin">16dp</dimen>
</resources>

3.  Open application app project gradle file and  add implement all dependencies :

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: "kotlin-kapt"

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "datanapps.roomapi"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

ext {
    supportLibVersion = "1.0.0"
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0'

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:design:28.0.0'

    // app compact
    implementation "androidx.appcompat:appcompat:1.1.0-alpha04"

    // constraint layout
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'

    // recycle view
    implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha04'

    // ROOM API
    implementation "androidx.room:room-runtime:2.0.0"
    kapt "androidx.room:room-compiler:2.0.0"


    // Run programm in background
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
repositories {
    mavenCentral()
}

4. Create an entity means a table (here i did for book)

  package datanapps.roomapi.roomdatabase

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

@Entity
class Book {
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0
    var bookTitle: String? = null
    var authorName: String? = null
    var publishedYear: Int = 0
}

5. Create an DAO class means a medium to access table record (here i did for BookDAO)

package datanapps.roomapi.roomdatabase

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update

@Dao
interface DaoBookAccess {

@Insert
fun insertTask(note: Book): Long?


/* @Query("SELECT * FROM Book ORDER BY created_at desc")
LiveData<List<Book>> fetchAllTasks();*/

@Query("SELECT * FROM Book")
fun fetchAllTasks(): LiveData<List<Book>>


@Query("SELECT * FROM Book WHERE id =:taskId")
fun getTask(taskId: Int): LiveData<Book>


@Update
fun updateTask(note: Book)


@Delete
fun deleteTask(note: Book)
}

6. Create a class for database means create a table for application

   package datanapps.roomapi.roomdatabase

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

@Database(entities = [Book::class], version = 1, exportSchema = false)
abstract class AppDB : RoomDatabase() {
    abstract fun daoBookAccess(): DaoBookAccess
}

 

7. Create a repository class to manage all  CRUD opertation in single class.

BookRepository.kt

package datanapps.roomapi.roomdatabase

import android.content.Context

import androidx.lifecycle.LiveData
import androidx.room.Room
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class BookRepository(context: Context) {

    private val DB_NAME = "db_task"
    private val appDatabase: AppDB

    init {
        appDatabase = Room.databaseBuilder(context, AppDB::class.java, DB_NAME).build()
    }

    fun insertTask(note: Book) {

        GlobalScope.launch {
            appDatabase.daoBookAccess().insertTask(note)
        }
    }

    fun updateBook(book: Book) {
        GlobalScope.launch {
            appDatabase.daoBookAccess().updateTask(book)
        }
    }

    fun deleteBookById(id: Int) {
        val book = getBookById(id)
        if (book != null) {
            deleteBook(book.value!!)
        }
    }

    fun deleteBook(note: Book) {
        GlobalScope.launch {
            appDatabase.daoBookAccess().deleteTask(note)
        }
    }

    fun getBookById(id: Int): LiveData<Book>? {
        return appDatabase.daoBookAccess().getTask(id)
    }

    val getAllBookList: LiveData<List<Book>>
        get() = appDatabase.daoBookAccess().fetchAllTasks()
}


8.  To display a layout in Recycleview, we create a layout for adapter which will inflate in adapter class.

layout_book_list.xml
<?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="250dp"
    android:background="@color/colorGrey"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">



    <TextView
        android:id="@+id/layout_book_list_title"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:textSize="40sp"
        android:padding="20dp"
        android:gravity="center|top"
        android:textStyle="bold"
       app:layout_constraintTop_toTopOf="parent"
        android:textColor="@color/colorAccent"
        tools:text="title" />


    <ImageView
        android:id="@+id/layout_book_list_delete"
        android:layout_width="30dp"
        android:layout_height="30dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:contentDescription="@string/app_name"
        app:layout_constraintTop_toTopOf="parent"
        android:src="@drawable/ic_delete"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="@color/colorBackTransparent_40"
        >


        <TextView
            android:id="@+id/layout_book_list_author"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="16dp"
            tools:text="Author"
           android:layout_alignParentTop="true"
            android:textColor="@android:color/black"
            />

        <TextView
            android:id="@+id/layout_book_list_year"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="16dp"
            tools:text="year"
            android:paddingEnd="5dp"
            android:layout_alignParentEnd="true"
            android:layout_below="@+id/layout_book_list_title"
            android:textColor="@android:color/black"
            />

    </RelativeLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

 

9.  Now going to create a adapter for recycle view and here we will use above created layout and model.  

BooksAdapter.kt

package datanapps.roomapi

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView

import androidx.recyclerview.widget.RecyclerView
import datanapps.roomapi.roomdatabase.Book

class BooksAdapter(private val context: Context) : RecyclerView.Adapter<BooksAdapter.UserViewHolder>() {


    private var moviesList: List<Book>
    private lateinit var deleteClickListener: View.OnClickListener
    init {
        moviesList = arrayListOf<Book>()
    }


    fun updateBookList(moviesList: List<Book>){
        this.moviesList = moviesList
        notifyDataSetChanged()
    }

    fun deleteClickListener(clickListener: View.OnClickListener){
       this.deleteClickListener = clickListener;
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val itemView = LayoutInflater.from(parent.context)
                .inflate(R.layout.layout_book_list, parent, false)

        return UserViewHolder(itemView)
    }


    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val book = moviesList[position]
        holder.bookName.text = book.bookTitle
        holder.bookAuthor.text = book.authorName
        holder.publishedYear.text = book.publishedYear.toString()
        holder.imageDelete.setTag(book)
        holder.imageDelete.setOnClickListener(deleteClickListener);


    }

    override fun getItemCount(): Int {
        return moviesList.size
    }

    inner class UserViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var bookName: TextView
        var bookAuthor: TextView
        var imageDelete: ImageView
        var publishedYear: TextView


        init {
            bookName = view.findViewById(R.id.layout_book_list_title)
            bookAuthor = view.findViewById(R.id.layout_book_list_author)
            imageDelete = view.findViewById(R.id.layout_book_list_delete)
            publishedYear = view.findViewById(R.id.layout_book_list_year)

        }
    }



}

 

10. Now open res >> layout >> activity.main.xml  and replace with below code.

activity.main.xml

 

<?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:id="@+id/root_layout"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycle_view_book"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:layout_marginTop="?android:attr/actionBarSize"
        app:layout_constraintTop_toBottomOf="@+id/appbar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="@+id/appbar"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />


    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_input_add"
        app:fabCustomSize="50dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

11.  Open Main activity and write this code.   

MainActivity.kt

package datanapps.roomapi

import android.os.Bundle
import android.os.Handler
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import datanapps.roomapi.roomdatabase.Book
import datanapps.roomapi.roomdatabase.BookRepository
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

    var booksAdapter = BooksAdapter(this@MainActivity)


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

        // set tool bar
        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        // set floating action
        val fab = findViewById<FloatingActionButton>(R.id.fab_bar)
        fab.setOnClickListener { view ->


            addBook()

        }

        // set recycle view
        setRecycleViewList()

    }


    private fun setRecycleViewList() {
        val recyclerView = findViewById<RecyclerView>(R.id.recycle_view_book)
        val mLayoutManager = LinearLayoutManager(applicationContext)
        recyclerView.layoutManager = mLayoutManager
        recyclerView.itemAnimator = DefaultItemAnimator()
        recyclerView.adapter = booksAdapter
        booksAdapter.deleteClickListener(View.OnClickListener {

            var book = it.getTag()
            if (book is Book) {
                deleteAlertDialog(book)


            }

        })
    }


    override fun onResume() {
        super.onResume()
        getBookListFromRecordFromDB()
    }


    private fun getBookListFromRecordFromDB() {
        Handler().postDelayed({
            val noteRepository = BookRepository(applicationContext)
            noteRepository.getAllBookList.observe(this, androidx.lifecycle.Observer {
                booksAdapter.updateBookList(it)
            })
        }, 1500)


    }


    private fun addBook() {
        val noteRepository = BookRepository(applicationContext)
        // Start a coroutine
        var book = Book()
        book.bookTitle = "Book Name"+(booksAdapter.itemCount+1)
        book.authorName = "Author "+(booksAdapter.itemCount+1)
        book.publishedYear = 2000 +(booksAdapter.itemCount+1)
        noteRepository.insertTask(book)
        getBookListFromRecordFromDB()
    }


    private fun deleteBook(book: Book){
        val noteRepository = BookRepository(applicationContext)
        noteRepository.deleteBook(book)
        getBookListFromRecordFromDB()
    }

    fun deleteAlertDialog(book: Book) {
        val builder = AlertDialog.Builder(this@MainActivity)

        // Set the alert dialog title
        builder.setTitle("Delete Book")

        // Display a message on alert dialog
        builder.setMessage("Are you want to delete this book")

        // Set a positive button and its click listener on alert dialog
        builder.setPositiveButton("YES") { dialog, which ->
            // Do something when user press the positive button
            Snackbar.make(root_layout, "Books Deleted", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show()
            deleteBook(book);
        }

        // Display a negative button on alert dialog
        builder.setNegativeButton("No") { dialog, which ->

        }


        // Finally, make the alert dialog using builder
        val dialog: AlertDialog = builder.create()

        // Display the alert dialog on app interface
        dialog.show()
    }

}

 

 

Please download project and sample here.

Download code :  https://github.com/datanapps/AndroidRoomAPI

Read More : https://developer.android.com/training/data-storage/room

---------------------------------------------

Also, check out our Blogging for developers : 
Android Exo Player

But in the meantime, you can suggest me in comments for next ' Title '. please share your thoughts, tips with us, I'm sure you have a good points so please comment below or mail us at datanapps@gmail.com.

Please If you enjoyed this post, I’d be very grateful if you’d help it spread by emailing it to a friend, or sharing it on Twitter or Facebook.

Thank you so much, Have a great day !

Next week I’ll post   Firebase Live Data  which is important for us in daily life.

 


Click Here To See More

What's Your Reaction?

like
1
dislike
0
love
0
funny
0
angry
0
sad
0
wow
0