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:
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>
Looks of the app. Listing all the books from database.
In addition you can find github repository also: