Room in Android

 

Useful Videos & Blogs :

https://youtu.be/qO56SL856xc

https://medium.com/mindorks/using-room-database-android-jetpack-675a89a0e942

https://www.techotopia.com/index.php/An_Android_Room_Database_and_Repository_Tutorial

Download database file :  https://youtu.be/3BfvnwrlO7E


The Room persistence library provides an abstraction layer over SQLite database in android to allow fluent database access while harnessing the full power of SQLite.


For SELECT queries, Room will infer the result contents from the method's return type and generate the code that will automatically convert the query result into the method's return type. For single result queries, the return type can be any data object (also known as POJOs). For queries that return multiple values, you can use List or Array. In addition to these, any query may return Cursor or any query result can be wrapped in a LiveData.


Always perform the Database Operations on a Background thread !! 


Recommedned Way to design a Room Operation design

There are three major components in Room :

  • The Database class that holds the database and serves as the main access point for the underlying connection to your app's persisted data.
  • Data entities that represent tables in your app's database.
  • Data access objects (DAOs) that provide methods that your app can use to query, update, insert, and delete data in the database.

The database class provides your app with instances of the DAOs associated with that database. In turn, the app can use the DAOs to retrieve data from the database as instances of the associated data entity objects. The app can also use the defined data entities to update rows from the corresponding tables, or to create new rows for insertion





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














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


To use Room add the below dependency :


KOTLIN :


def room_version = "2.2.5"

implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"

// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"

// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"


JAVA:


def room_version = "2.2.5"

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

// optional - RxJava support for Room
implementation "androidx.room:room-rxjava2:$room_version"

// optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version"

// optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version"



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


Room in JAVA 






<?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"
tools:context=".MainActivity">

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="54dp"
android:text="Hello World!"
android:textSize="25sp"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />


<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:text="insert"
android:onClick="insert_data"
app:layout_constraintStart_toStartOf="@+id/button2"
app:layout_constraintTop_toBottomOf="@+id/button2" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="210dp"
android:text="fetch"
android:onClick="fetch_data"
app:layout_constraintStart_toStartOf="@+id/textView"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>


MainActivity.java

package com.deepesh.myroomapp;

import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.util.List;

public class MainActivity extends AppCompatActivity {

static CustomerDatabase db;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// IMPORTANT
// This database class object contains a method
// that returns a DAO class object
// which is used to invoke the methods inside DAO
db = CustomerDatabase.getInstance(this);
}

// user clicks button
public void insert_data(View view) {
new insert_async().execute("hello");
}

// user clicks button
public void fetch_data(View view) {
new findCustomer_async().execute("Hi");
}



// We should do all the Database operations on a background thread.
// Hence we use a Asynctask
// You can also update the UI in onPostExecute() method.

static class insert_async extends AsyncTask<String,String,String>{

@Override
protected String doInBackground(String... strings) {

Customer customer1 = new Customer("Deepesh","Mumbai");
db.getCustomerDao().insertCustomer(customer1);

return null;
}


}


static class findCustomer_async extends AsyncTask<String,String,String>{

@Override
protected String doInBackground(String... strings) {

List<Customer> customerList= db.getCustomerDao().findCustomer("Deepesh");

Customer c1 = customerList.get(0);

Log.d("TAG", "CITY IS "+c1.city );

return null;
}

}

}



ENTITY CLASS ( Customer.java)

package com.deepesh.myroomapp;

import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;

@Entity(tableName = "customers")
public class Customer {

@PrimaryKey(autoGenerate = true)
int id;

@ColumnInfo(name = "name")
String name;

String city;


public Customer(String name, String city) {
this.name = name;
this.city = city;
}

// IGNORE THIS CONSTRUCTOR TO AVOID MAKING OBJECT USING THAT.
@Ignore
public Customer(int id ,String name, String city) {
this.id=id;
this.name = name;
this.city = city;
}

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 getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}


}


DAO CLASS ( customerDao.java )

package com.deepesh.myroomapp;

import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;


@Dao
public interface customerDao {

@Insert
void insertCustomer(Customer customer);


// use : to specify parameters in the sql query

@Query("Select * from customers where name= :user_name ")
List<Customer> findCustomer(String user_name);


@Query("Select * from customers")
List<Customer> getAllCustomers();

}


DATABASE CLASS  (CustommerDatabase.java )

package com.deepesh.myroomapp;

import android.content.Context;

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

// Pass all the entities you have created , and also pass the version number of the db.
@Database(entities = Customer.class,version = 1)
public abstract class CustomerDatabase extends RoomDatabase {

// Database class must contain 2 things :
// 1] Abstract method which returns the DAO class object
// 2] Method that returns an instance of Database class

public abstract customerDao getCustomerDao();

public static CustomerDatabase instance;


public static CustomerDatabase getInstance(Context context){

if (instance==null){
String DB_NAME = "customers_database";
instance= Room.databaseBuilder(context.getApplicationContext(),CustomerDatabase.class, DB_NAME).build();
}

return instance;
}

}



EXAMPLE 2  :


<?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"
tools:context=".MainActivity">


<Button
android:id="@+id/store_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="194dp"
android:layout_marginEnd="127dp"
android:onClick="StoreData"
android:text="Store Data"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/getdata_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="94dp"
android:layout_marginEnd="9dp"
android:onClick="GetData"
android:text="Get Data"
app:layout_constraintEnd_toEndOf="@+id/store_button"
app:layout_constraintTop_toBottomOf="@+id/store_button" />
</androidx.constraintlayout.widget.ConstraintLayout>


package com.deepesh.exampleapp4;

import androidx.appcompat.app.AppCompatActivity;
import androidx.room.ColumnInfo;
import androidx.room.Dao;
import androidx.room.Database;
import androidx.room.Entity;
import androidx.room.Insert;
import androidx.room.PrimaryKey;
import androidx.room.Query;
import androidx.room.Room;
import androidx.room.RoomDatabase;

import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.util.List;

import static android.content.ContentValues.TAG;


public class MainActivity extends AppCompatActivity {

MyDatabase db;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

db = MyDatabase.getInstance(this);

}

public void StoreData(View view) {

new Thread(() -> {
MyEntity entity = new MyEntity("Deepesh","Mhatre");
db.getMyDao().insertUser(entity);
Log.d(TAG, "StoreData: Data Inserted Sucessfully !");
}).start();

}

public void GetData(View view){

new Thread(() -> {
List<MyEntity> users = db.getMyDao().getAllUsers();
MyEntity user1 = users.get(0);
Log.d(TAG, "UserId: " + user1.getUserId() + " NAME: "
+ user1.getFirstname() + " SURNAME: "+user1.getLastname());
}).start();

}



// ========================================================

// Entity Class

final static String TABLE_NAME = "MyUsers_Table";

@Entity(tableName = TABLE_NAME)
public static class MyEntity {

@PrimaryKey(autoGenerate = true)
int userId;

@ColumnInfo(name = "firstname")
String firstname;

@ColumnInfo(name = "lastname")
String lastname;

public MyEntity(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}

public int getUserId() {
return userId;
}

public void setUserId(int userId) {
this.userId = userId;
}

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}


}

// ========================================================

// DAO interface

@Dao
public interface MyDAO {

@Insert
void insertUser(MyEntity myEntity);

// use : to specify parameters in the sql query

@Query("Select * from " + TABLE_NAME + " where firstname= :username ")
List<MyEntity> findUser(String username);


@Query("Select * from " + TABLE_NAME)
List<MyEntity> getAllUsers();

}


// ========================================================

// Database Class
@Database(entities = MyEntity.class, version = 1)
public abstract static class MyDatabase extends RoomDatabase {

public abstract MyDAO getMyDao();

public static MyDatabase instance;


public static MyDatabase getInstance(Context context) {

if (instance == null) {
String DB_NAME = "customers_database";
instance = Room.databaseBuilder(context.getApplicationContext(), MyDatabase.class, DB_NAME).build();
}

return instance;
}

}


}




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


ADD CALLBACK METHOD TO BE CALLED WHEN DATABASE IS OPENED /CREATED


package com.deepesh.notster2;

import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.sqlite.db.SupportSQLiteDatabase;

@Database(entities = Note.class, version = 1)
public abstract class NoteDatabase extends RoomDatabase {

private static NoteDatabase instance;

// Room autogenerates the implementation code for it.
public abstract NoteDao getNoteDao();

public static synchronized NoteDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context.getApplicationContext(), NoteDatabase.class, "Database_File")
.fallbackToDestructiveMigration()
// attach the callback
.addCallback(roomcallback)
.build();
}
return instance;
}

//----------------------------------------------------------------------------------

// Fill Some Notes already so that we dont start with an Empty Database on recylerview.

private static RoomDatabase.Callback roomcallback = new RoomDatabase.Callback(){

// Called only once when Db is created
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);

new PopulateDbAsyncTask(instance).execute();
}


// Called everytime database is opened
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
};


private static class PopulateDbAsyncTask extends AsyncTask<Void,Void,Void>{

NoteDao noteDao;

PopulateDbAsyncTask(NoteDatabase noteDatabase){
noteDao = noteDatabase.getNoteDao();
}
@Override
protected Void doInBackground(Void... voids) {
noteDao.insertNote(new Note("Title 1","This is test data1"));
noteDao.insertNote(new Note("Title 2","This is test data1"));
noteDao.insertNote(new Note("Title 3","This is test data3"));
return null;
}
}



}






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


























Comments

Popular posts from this blog

React Js + React-Redux (part-2)

React Js + CSS Styling + React Router (part-1)

ViteJS (Module Bundlers, Build Tools)