Ultimate Room db tutorial: install Room DB in Android app

If you need to save data locally in your app, room database will be the best database system for android. Today we will describe room db tutorial and learn how to implement and use room database in android using java.

Step 1: Installing Room DB

Firstly, open your project level build.gradle. Paste the code below in dependencies and android’s defaultConfig block.

dependencies {
    ....
    ....
    //room database
    implementation 'androidx.room:room-runtime:2.4.1'
    annotationProcessor 'androidx.room:room-compiler:2.4.1'

}
android {
    
    ....
    ....

    defaultConfig {
        ....
        ....

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }
}

Your schema file of your database version will be saved in schemas folder.

Step 2: Create tables

Let’s create a new package and name it db. We will create all the files related to database in this package.

Now create another package in db. Name it tables. Let’s say we want to create a table of books. In book table we want to have id, name, author, publishDate, createdAt and updatedAt columns. So in tables package create a class named Book. Paste the code below:

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

@Entity
public class Book {
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String name;
    private String author;
    private long publishDate;
    private long createdAt;
    private long updatedAt;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public long getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(long publishDate) {
        this.publishDate = publishDate;
    }

    public long getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(long createdAt) {
        this.createdAt = createdAt;
    }

    public long getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(long updatedAt) {
        this.updatedAt = updatedAt;
    }
}

Here @Entity means we are declaring this class as table and @PrimaryKey(autoGenerate = true) to make the field id as primary key and auto increment.

Step 2: Create DAO

Likewise, construct another package in db and name it dao(Data Access Object). We will keep all the daos here. Next, create an interface named BookDao and paste the code below:

import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;

import com.captaindroid.roomdbtutorial.db.tables.Book;

import java.util.List;

@Dao
public interface BookDao {
    @Insert
    long insertBook(Book book);

    @Update
    int updateBook(Book book);

    @Query("Select * from book")
    List<Book> getAllBooks();
}

@Dao annotation used to declare an interface as DAO. You can read in details about all annotations here.

Step 3: Create AppDatabase

After that, in db package create another class and name it AppDatabase. Paste the code below:

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

import com.captaindroid.roomdbtutorial.db.dao.BookDao;
import com.captaindroid.roomdbtutorial.db.tables.Book;

@Database(entities = {Book.class}, exportSchema = true, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract BookDao getBookDao();
}

Step 4: Create DbClient

Similarly, create another class in db package and name it DbClient. Paste the code below:

import android.content.Context;

import androidx.room.Room;

public class DbClient {
    private Context mCtx;
    private static DbClient mInstance;

    private AppDatabase appDatabase;

    private DbClient(Context mCtx) {
        this.mCtx = mCtx;
        appDatabase = Room.databaseBuilder(mCtx, AppDatabase.class, "Captaindroid")
                .allowMainThreadQueries()
                .build();
    }

    public static synchronized DbClient getInstance(Context mCtx) {
        if (mInstance == null) {
            mInstance = new DbClient(mCtx);
        }
        return mInstance;
    }

    public AppDatabase getAppDatabase() {
        return appDatabase;
    }
}

Here is the package and classes structure:

Room db tutorial

Image of package structure.

Step 5: Run and test app

In addition here is the codes describing the usage of the whole project. For instance, you can now run and test the app using the codes below.

MainActivity:

package com.captaindroid.roomdbtutorial;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.captaindroid.roomdbtutorial.databinding.ActivityMainBinding;
import com.captaindroid.roomdbtutorial.databinding.RowBookBinding;
import com.captaindroid.roomdbtutorial.db.DbClient;
import com.captaindroid.roomdbtutorial.db.tables.Book;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;

    private List<Book> books = new ArrayList<>();
    private Adapter adapter;
    private DbClient dbClient;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd EEE yy, hh:mm");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        dbClient = DbClient.getInstance(this);
        adapter = new Adapter();

        books.addAll(dbClient.getAppDatabase().getBookDao().getAllBooks());

        binding.rvBookList.setLayoutManager(new LinearLayoutManager(this));
        binding.rvBookList.setAdapter(adapter);

        binding.btAddBook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book();
                book.setName("Book " + System.currentTimeMillis());
                book.setAuthor("Author " + System.currentTimeMillis());
                book.setPublishDate(System.currentTimeMillis());
                book.setCreatedAt(System.currentTimeMillis());
                book.setUpdatedAt(System.currentTimeMillis());

                dbClient.getAppDatabase().getBookDao().insertBook(book);

                books.clear();
                books.addAll(dbClient.getAppDatabase().getBookDao().getAllBooks());
                adapter.notifyDataSetChanged();
            }
        });

    }

    private class Adapter extends RecyclerView.Adapter<ViewHolder>{

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new ViewHolder(RowBookBinding.inflate(getLayoutInflater(), parent, false));
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.rowBookBinding.tvId.setText(books.get(position).getId() + "");
            holder.rowBookBinding.tvBookName.setText(books.get(position).getName());
            holder.rowBookBinding.tvAuthorName.setText(books.get(position).getAuthor());
            holder.rowBookBinding.tvPublishDate.setText(simpleDateFormat.format(new Date(books.get(position).getPublishDate())));

            if(position == books.size() - 1){
                holder.rowBookBinding.vLastDiv.setVisibility(View.VISIBLE);
            }else {
                holder.rowBookBinding.vLastDiv.setVisibility(View.GONE);
            }
        }

        @Override
        public int getItemCount() {
            return books.size();
        }
    }

    private class ViewHolder extends RecyclerView.ViewHolder{
        RowBookBinding rowBookBinding;
        public ViewHolder(RowBookBinding rowBookBinding) {
            super(rowBookBinding.getRoot());
            this.rowBookBinding = rowBookBinding;
        }
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:background="#858585"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:paddingLeft="15dp"
            android:textColor="@color/black"
            android:layout_weight="0.4"
            android:text="Id"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <TextView
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <TextView
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Author"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <TextView
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Publish Date"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <LinearLayout
        android:layout_weight="1"
        android:padding="15dp"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rvBookList"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <Button
            android:id="@+id/btAddBook"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add Book"
            android:layout_gravity="bottom|center" />
    </LinearLayout>

</LinearLayout>

row_book:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <View
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height=".5dp"/>
    <LinearLayout
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="30dp">
        <View
            android:layout_marginRight="2dp"
            android:background="@color/black"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"/>
        <TextView
            android:gravity="center"
            android:id="@+id/tvId"
            android:textColor="@color/black"
            android:layout_weight="0.2"
            android:text="Id"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <View
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp"
            android:background="@color/black"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"/>
        <TextView
            android:singleLine="true"
            android:id="@+id/tvBookName"
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <View
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp"
            android:background="@color/black"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"/>
        <TextView
            android:singleLine="true"
            android:id="@+id/tvAuthorName"
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Author"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <View
            android:layout_marginLeft="2dp"
            android:layout_marginRight="2dp"
            android:background="@color/black"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"/>
        <TextView
            android:singleLine="true"
            android:id="@+id/tvPublishDate"
            android:textColor="@color/black"
            android:layout_weight="1"
            android:text="Publish Date"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>
        <View
            android:layout_marginLeft="2dp"
            android:background="@color/black"
            android:layout_width="0.5dp"
            android:layout_height="match_parent"/>
    </LinearLayout>

    <View
        android:id="@+id/vLastDiv"
        android:background="@color/black"
        android:layout_width="match_parent"
        android:layout_height=".5dp"/>

</LinearLayout>
Room db tutorial: room database

Looks of the app. Listing all the books from database.

In addition you can find github repository also: