Getting Started with Room

Overview

Android provides a set of libraries to help to design of a highly maintainable and robust code. They have provided with helper classes for better data caching and handling UI component states.

Room

The Room is a robust SQL object mapping library. It provides a layer of Abstraction over the Android’s SQLite Database. Allowing us to fluently access the power of SQLite database.

There are 3 major components in Room:

  1. Database:
    Contains the database holder and serves as the main access point for the app’s persisted relational data.
  2. Entity:
    Represents a table within the database.
  3. DAO:
    Contains the methods used for accessing the database.
Architecture Diagram

Boiler Plate Code

In this tutorial we will be making a very basic Todo Application, that will perform CRUD operations using the Room Database.

Todo App
Boilerplate Project Structure

The boilerplate code can create, update and delete a todo/memo. However, the data won’t persist as soon as the app is closed.

Our main screen is a having a recyclerview to list all of our todos. The model of the todo is saved in the model package which is as below:

[code language=”java”]

public class Todo {
private long _id;

private String todoTitle;

private String todoText;

private long timeStamp;

public long get_id() {
return _id;
}

public void set_id(long _id) {
this._id = _id;
}

public String getTodoTitle() {
return todoTitle;
}

public void setTodoTitle(String todoTitle) {
this.todoTitle = todoTitle;
}

public String getTodoText() {
return todoText;
}

public void setTodoText(String todoText) {
this.todoText = todoText;
}

public long getTimeStamp() {
return timeStamp;
}

public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
}

[/code]
We will be using this class as an Entity (Table) for our database. Through annotations, Room makes it much easier to define the properties of the table. Annotations like PrimaryKey, ColumnInfo are quite understandable by name.

A table is created using @Entity annotation and the ‘tableName’ attributes are used to provide a table name. We define primary key of the table using @PrimaryKey annotation and columns of the table using @ColumnInfo annotation and their respective names with a name attribute.

Our model class after adding annotations will look as below:

[code language=”java”]

@Entity(tableName = “todo”)
public class Todo {
@PrimaryKey
private long _id;

@ColumnInfo(name = “title”)
private String todoTitle;

@ColumnInfo(name = “text”)
private String todoText;

@ColumnInfo(name = “time”)
private long timeStamp;

public long get_id() {
return _id;
}

public void set_id(long _id) {
this._id = _id;
}

public String getTodoTitle() {
return todoTitle;
}

public void setTodoTitle(String todoTitle) {
this.todoTitle = todoTitle;
}

public String getTodoText() {
return todoText;
}

public void setTodoText(String todoText) {
this.todoText = todoText;
}

public long getTimeStamp() {
return timeStamp;
}

public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
}
[/code]
Next, We will be making our interface for performing CRUD operations.

The dao interface has to be annotated with @Dao annotation. We use @Query annotation for executing a query and @Insert, @Update and @Delete for insertion, deletion, and updating respectively.

The dao interface will finally look as below:

[code language=”java”]
@Dao
public interface AppDao {
@Query(“Select * from ” + AppConstants.DB_NAME + ” order by time desc”)
List getAllTodos();

@Query(“Select * from ” + AppConstants.DB_NAME + ” where _id = :id order by time desc”)
Todo getTodo(String id);
@Insert
void insertTodo(Todo todo);

@Update
void updateTodo(Todo todo);

@Delete
void deleteTodo(Todo todo);
}
[/code]
Attribute values can also be passed via interface method arguments and are used in queries with ‘:’ sign. As we can see in case of ‘getTodo’.

And at last, we will create an abstract Database Class that will extend RoomDatabase class.
Database class is created through @Database annotation, it is mandatory to specify entities and version of the database. In our Database class, we will add access methods of our each Dao class.

The AppDatabase class is as below:

[code language=”java”]
@Database(entities = {Todo.class}, version = 1) extends RoomDatabase {
public abstract AppDao appDao();
}
[/code]
We will also be using a Singleton class to get the reference to our AppDao interface. Which is as below:

[code language=”java”]
public class AppDBHandler {
private AppDao appdao;
private static AppDBHandler ourInstance;

public static AppDBHandler getInstance(Context context) {
if(ourInstance == null) {
ourInstance = new AppDBHandler(context);
}
return ourInstance;
}

private AppDBHandler(Context context) {
AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, AppConstants.DB_NAME).build();
appdao = db.appDao();
}

public AppDao getAppDao() {
return appdao;
}
}
[/code]
At last, we are all done with setting up database boilerplate for the project. Now the only thing left to do is adding database operations in our project using our Dao interface.

The Room directly maps the database model to our Java Bean.

In our MainActivity.class, we will add following lines to retrieve the list of all todos. Just below setting adapter to our recyclerview.

[code language=”java”]
MainActivity.java


recyclerView.setAdapter(todoListAdapter);
final AppDao dao = AppDBHandler.getInstance(getApplicationContext()).getAppDao();
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
todos.addAll(dao.getAllTodos());
runOnUiThread(new Runnable() {
@Override
public void run() {
todoListAdapter.notifyItemRangeInserted(0, todos.size());
}
});
}
});
T1.start();
[/code]

Note: All the database calls in Room are synchronous and run on same thread to which they are called. If the call is a made on UI thread, then it will throw a IllegalStateException.

[code language=”java”]
MainActivity.java


case 1: {
final AppDao dao = AppDBHandler.getInstance(getApplicationContext()).getAppDao();
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
dao.deleteTodo(todos.get(position));
todos.remove(position);
runOnUiThread(new Runnable() {
@Override
public void run() {
Snackbar.make(parentLayout, “Todo Deleted”, Snackbar.LENGTH_SHORT).show();
todoListAdapter.notifyItemRemoved(position);
}
});
}
});
T1.start();
break;
}
[/code]
We are using a single Dialog for creating and editing new todos. In our logic, we are using a private Todo class reference null value of which signifies whether the action is an update or a create action. We will modify our existing logic as below:

[code language=”java”]
CreateTodoDialog.java


@Override
public void onClick(View view) {


if(this.todo == null) {
todo = new Todo();
todo.set_id(System.currentTimeMillis());
todo.setTimeStamp(System.currentTimeMillis());
todo.setTodoTitle(edtTitle.getText().toString());
todo.setTodoText(edtText.getText().toString());
final AppDao dao = AppDBHandler.getInstance(getContext()).getAppDao();
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
dao.insertTodo(todo);
dataCallbackListener.onDataReceived(todo);
}
});
T1.start();
} else {
todo.setTimeStamp(System.currentTimeMillis());
todo.setTodoTitle(edtTitle.getText().toString());
todo.setTodoText(edtText.getText().toString());
final AppDao dao = AppDBHandler.getInstance(getContext()).getAppDao();
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
dao.updateTodo(todo);
dataCallbackListener.onDataReceived(todo);
}
});
T1.start();
}
[/code]
And that’s it, the Room itself will use the provided pojo for performing insert and update operations.

Remarks

I believe that it will be very helpful in creating applications that require data caching and have well structure models for reusability. Especially, e-commerce applications in which we can model our product details like and can easily use them in carts and product info sections (Eg. quantity, favorites) where we can prevent unnecessary API calls.


Posted

in

by

Recent Post

  • Generative AI for IT: Integration approaches, use cases, challenges, ROI evaluation and future outlook

    Generative AI is a game-changer in the IT sector, driving significant cost reductions and operational efficiencies. According to a BCG analysis, Generative AI (GenAI) has the potential to deliver up to 10% savings on IT spending—a transformation that is reshaping multiple facets of technology. The impact is especially profound in application development, where nearly 75% […]

  • Generative AI in Manufacturing: Integration approaches, use cases and future outlook

    Generative AI is reshaping manufacturing by providing advanced solutions to longstanding challenges in the industry. With its ability to streamline production, optimize resource allocation, and enhance quality control, GenAI offers manufacturers new levels of operational efficiency and innovation. Unlike traditional automation, which primarily focuses on repetitive tasks, GenAI enables more dynamic and data-driven decision-making processes, […]

  • Generative AI in Healthcare: Integration, use cases, challenges, ROI, and future outlook

    Generative AI (GenAI) is revolutionizing the healthcare industry, enabling enhanced patient care, operational efficiency, and advanced decision-making. From automating administrative workflows to assisting in clinical diagnoses, GenAI is reshaping how healthcare providers, payers, and technology firms deliver services. A Q1 2024 survey of 100 US healthcare leaders revealed that over 70% have already implemented or […]

  • Generative AI in Hospitality: Integration, Use Cases, Challenges, and Future Outlook

    Generative AI is revolutionizing the hospitality industry, redefining guest experiences, and streamlining operations with intelligent automation. According to market research, the generative AI market in the hospitality sector was valued at USD 16.3 billion in 2023 and is projected to skyrocket to USD 439 billion by 2033, reflecting an impressive CAGR of 40.2% from 2024 […]

  • Generative AI for Contract Management: Overview, Use Cases, Implementation Strategies, and Future Trends

    Effective contract management is a cornerstone of business success, ensuring compliance, operational efficiency, and seamless negotiations. Yet, managing complex agreements across departments often proves daunting, particularly for large organizations. The TalkTo Application, a generative AI-powered platform, redefines contract management by automating and optimizing critical processes, enabling businesses to reduce operational friction and improve financial outcomes. […]

  • Generative AI in customer service: Integration approaches, use cases, best practices, and future outlook

    Introduction The rise of generative AI is revolutionizing customer service, heralding a new era of intelligent, responsive, and personalized customer interactions. As businesses strive to meet evolving customer expectations, these advanced technologies are becoming indispensable for creating dynamic and meaningful engagement. But what does this shift mean for the future of customer relationships? Generative AI […]

Click to Copy