In this article, We are going to learn how to implement the Room Database in Android Application.
Room is a persistence library part of Android Jetpack Components. It provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
The major difference between Room and SQLite are:
There are three major components in the Room:
1 |
@PrimaryKey(autoGenerate = true) |
1 |
@ColumnInfo(name = “column_name”) |
@Embeded — nested POJO/Models can be referenced directly in the SQL queries.
1. Create a new project in Android Studio by navigating to File ⇒ New ⇒ New Project and fill the required details. By default my activity is MainActivity.java.
2. First we have to add Room dependency to our project. Open the build.gradle at the app level and add the below dependencies to it and sync your project.
1 2 3 4 |
def room_version = "2.2.6" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" |
3. Once your project is synced then we have to create the UI to take user input for storing the data. Open activity_main.xml and add the below code to it. The layout contains three EditText to take input and a ListView to show the stored data.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
<?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" android:padding="16dp" tools:context=".MainActivity"> <EditText android:id="@+id/etUserName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/etEmail" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Enter Email" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/etUserName" /> <EditText android:id="@+id/etNumber" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:hint="Enter Number" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/etEmail" /> <Button android:id="@+id/btnSaveData" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:onClick="saveData" android:text="Save Data" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/etNumber" /> <Button android:id="@+id/btnShowData" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:onClick="showData" android:text="Show Data" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btnSaveData" /> <CheckBox android:id="@+id/updateCheckBox" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Update (will update the data on checked)" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btnShowData" /> <ListView android:id="@+id/listview_data" android:layout_width="match_parent" android:layout_height="0dp" app:layout_constraintBottom_toTopOf="@+id/btnSaveToEmployee" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/updateCheckBox" /> </androidx.constraintlayout.widget.ConstraintLayout> |
4. Now we have to create our table i.e. Entity. For this create a new class with the name User.java and put the below code into it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.Ignore; import androidx.room.PrimaryKey; @Entity(tableName = "table_user") public class User { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "row_id") private int id; @ColumnInfo(name = "name") private String name; @ColumnInfo(name = "email") private String email; @ColumnInfo(name = "phone_number") private String number; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public int getId() { return id; } public void setId(int id) { this.id = id; } } |
5. After creating Entity we have to create Dao to do CRUD operations. For this create a new interface called UserDao.java and put the below code into it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.Update; import java.util.List; @Dao public interface UserDao{ @Insert(onConflict = OnConflictStrategy.REPLACE) long insert(User user); @Query("select * from table_user") List<User> getAllUsers(); @Delete int delete(User user); @Update int update(User user); } |
6. Now we have to create our Database. Create an abstract class called MyDatabase.java and extent it with RoomDatabase.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import androidx.room.Database; import androidx.room.RoomDatabase; @Database(entities = {User.class}, version = 1) public abstract class MyDatabase extends RoomDatabase { public abstract UserDao userDao(); } |
7. We have created all components of the Room Database. No open your MainActivity.java and paste the below code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import androidx.appcompat.app.AppCompatActivity; import androidx.core.os.HandlerCompat; import androidx.room.Room; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import android.view.View; import android.widget.AdapterView; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { private EditText userName, email, number; private ListView listView; private ListAdapter listAdapter; private CheckBox checkBox; private MyDatabase db; private ExecutorService executorService = Executors.newSingleThreadExecutor(); private Handler handler = HandlerCompat.createAsync(Looper.getMainLooper()); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initDB(); userName = findViewById(R.id.etUserName); email = findViewById(R.id.etEmail); number = findViewById(R.id.etNumber); listView = findViewById(R.id.listview_data); checkBox = findViewById(R.id.updateCheckBox); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { User user = (User) listAdapter.getItem(i); executorService.execute(new Runnable() { @Override public void run() { if (checkBox.isChecked()) { int rowsAffected = db.userDao().update(user); handler.post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "Number of rows affected : " + rowsAffected, Toast.LENGTH_SHORT).show(); if (rowsAffected > 0) { listAdapter.notifyDataSetChanged(); } } }); } else { int rowsAffected = db.userDao().delete(user); handler.post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "Number of rows affected : " + rowsAffected, Toast.LENGTH_SHORT).show(); if (rowsAffected > 0) { listAdapter.removeData(i); } } }); } } }); } }); } /* method to init room database*/ private void initDB() { db = Room.databaseBuilder(getApplicationContext(), MyDatabase.class, "my_database") .fallbackToDestructiveMigration() .build(); } public void saveData(View view) { String getName = userName.getText().toString().trim(); String getEmail = email.getText().toString().trim(); String getNumber = number.getText().toString().trim(); if (TextUtils.isEmpty(getName) || TextUtils.isEmpty(getEmail) || TextUtils.isEmpty(getNumber)) { Toast.makeText(this, "Please enter all the inputs.", Toast.LENGTH_SHORT).show(); } else { User user = new User(); user.setName(getName); user.setEmail(getEmail); user.setNumber(getNumber); executorService.execute(new Runnable() { @Override public void run() { long id = db.userDao().insert(user); handler.post(new Runnable() { @Override public void run() { if (id > 0) { Toast.makeText(MainActivity.this, "Data Insertion success.", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Data Insertion failed.", Toast.LENGTH_SHORT).show(); } } }); } }); } } public void showData(View view) { executorService.execute(new Runnable() { @Override public void run() { List<User> userList = db.userDao().getAllUsers(); handler.post(new Runnable() { @Override public void run() { listAdapter = new ListAdapter(MainActivity.this, userList); listView.setAdapter(listAdapter); } }); } }); } } |
In the MainActivity we are doing the following things:
1 2 3 4 |
MyDatabase db = Room.databaseBuilder(getApplicationContext(), MyDatabase.class, "my_database") .fallbackToDestructiveMigration() .build(); |
1 |
long id = db.userDao().insert(user); |
1 |
List<User> userList = db.userDao().getAllUsers(); |
1 |
int rowsAffected = db.userDao().delete(user); |
1 |
int rowsAffected = db.userDao().update(user); |
Note: We cannot run Room queries on the main thread. So if you see the MainActivity code all the DB Opertations are inside ExeceutorsService to run the queries on the background thread. Alternatives of Executors are RxJava, Coroutines, Guava.
8. Now create ListAdapter.java class to list the fetched User from the database and add the below code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/* * Created by Androhub on 14/1/21 * Copyright (c) 2021 . All rights reserved. */ package com.androhub.roomdatabasedemo; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.CompoundButton; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class ListAdapter extends BaseAdapter { private final Context context; private final List<User> userList; private LayoutInflater inflater; public ListAdapter(Context context, List<User> userList) { this.context = context; this.userList = userList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return userList.size(); } @Override public Object getItem(int i) { return userList.get(i); } @Override public long getItemId(int i) { return i; } public void removeData(int index){ userList.remove(index); notifyDataSetChanged(); } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder = null; if (view == null) { view = inflater.inflate(R.layout.item_list, viewGroup, false); viewHolder = new ViewHolder(view); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } User user = userList.get(i); viewHolder.bindData(user); return view; } private static class ViewHolder { private TextView label; public ViewHolder(View view) { label = view.findViewById(R.id.item_data); } void bindData(User user) { label.setText(user.getName() + " ---- " + user.getEmail() + " ---- " + user.getNumber()); } } } |
9. Create item_list.xml for ListAdapter and add the below code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:padding="16dp" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <TextView android:layout_width="match_parent" android:id="@+id/item_data" app:layout_constraintTop_toTopOf="parent" app:layout_constraintEnd_toEndOf="parent" tools:text="Data" android:textSize="16sp" app:layout_constraintStart_toStartOf="parent" android:layout_height="wrap_content"/> </androidx.constraintlayout.widget.ConstraintLayout> |
10. Finally, all done. Now you can also integrate Room Database into your application.
Thanks.
Subscribe to us and get the latest news.