Android Jetpack’s Room with LiveData by Kotlin & Java

I have been working on a client’s project which involves updating data in real-time and storing in Android’s memory(SQLite) then fetch it whenever needed

The problem arose when I want to use the data, I could not know if what I just fetched is the actual current data. This is a problem because the data is very sensitive…fuel prices.

The solution I came up with was using Room mixed with LiveData and it worked perfectly for my use-case.

Today there will be less talk and more code 😀

Room is an abstraction layer for SQLite, It helps you to perform queries in a simple way. Its a part of Android’s Jetpack

LiveData is also a part of Android Jetpack Library which notifies views when underlying database/data changes its lifecycle aware meaning when the particular activity/fragment is active, it’s only time that it works.

Now I will make a simple Android(Java) App which updates the fuel prices and update the UI in real-time

FIRST CREATE AN ANDROID PROJECT WITH JAVA SUPPORT ( Kotlin Code will come soon)

THEN: import a Room library in Gradle using the following code then Build

implementation "android.arch.persistence.room:runtime:1.1.1"
annotationProcessor "android.arch.persistence.room:compiler:1.1.1"

Now we create an SQLite Table and Database using Room

To create a table in Room, you create a Class and name it PetrolPrice.java

To turn that class into a TABLE you add an annotation called Entity on top of it like the following

@Entity
public class PetrolPrice {
}

The above code shows that we have a Table(in this case Entity) called PetrolPrice.

What do we add after adding a Table? That’s right. COLUMNS

To make columns in Room we create them like this

@PrimaryKey(autoGenerate = true)
int id;

@ColumnInfo(name = "fuel_price")
double fuel_price;

To explain the code above, we have 2 columns called ID and FUEL_PRICE

ID is an integer that I made it Primary Key by annotating it @PrimaryKey and made it autogenerate the ID by itself.

FUEL_PRICE is a column with a double datatype and I made it a Column by annotating it by @ColumnInfo

Now we have to add a constructor, getters and setters…like we do in all models.

In the End, our PETROLPRICE.JAVA class will be like this

PetrolPrice.java
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity
public class PetrolPrice {

    @PrimaryKey(autoGenerate = true)
    int id;

    @ColumnInfo(name = "fuel_price")
    double fuel_price;

    public PetrolPrice(int id, double fuel_price) {
        this.id = id;
        this.fuel_price = fuel_price;
    }

    public PetrolPrice() {
    }

    public int getId() {
        return id;
    }

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

    public double getFuel_price() {
        return fuel_price;
    }

    public void setFuel_price(double fuel_price) {
        this.fuel_price = fuel_price;
    }
}

Now there is something called Data Access Object or DAO. They are the main component in your Room Database. They process the queries and stuff

You declare them by using interfaces. Now I am making a DAO called PetrolPriceDao.java that will perform CRUD operations (Create, Read, Update, Delete)

PetrolPriceDao.java
import androidx.lifecycle.LiveData;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;

import com.nickyrabit.roomwithlivedata.room_db.model.PetrolPrice;

import java.util.List;

public interface PetrolPriceDao {
    @Insert
    Long insert(PetrolPrice c);

    //WHERE WE ARE FOCUSING ON THIS ARTICLE
    @Query("SELECT * FROM 'PetrolPrice'")
    LiveData<List<PetrolPrice>> getAllConstants();

    @Update
    void update(PetrolPrice c);

    @Query("SELECT * FROM `PetrolPrice` WHERE `id` =:id")
    PetrolPrice getConstant(int id);

    @Delete
    void delete(PetrolPrice c);
}

Looking at the above code we are annotating a function which we want the query to do, That’s what’s best in Room!

I have set a LIVEDATA on PetrolPriceList which has the task of alerting all Observer object when there is a change in a particular data in our case, PetrolPrice.

A quick explanation on code above @Query() is an annotation that will hold all SQLite queries because Room can perform only some few basic queries without typing them.

Now let’s Go to Creating a Database, We create a new function called FuelPriceDatabase we will define the tables and database here. By annotations as usual

 FuelPriceDatabase.java 
@Database(entities = {PetrolPrice.class}, version = 1, exportSchema = false)
public abstract class FuelPriceDatabase extends RoomDatabase {
    public abstract PetrolPriceDao constantsDao();

    private static FuelPriceDatabase INSTANCE;

    public static FuelPriceDatabase getAppDatabase(Context context) {
        if (INSTANCE == null) {
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(), FuelPriceDatabase.class, "apos-database").build();
        }
        return INSTANCE;
    }

    public static void destroyInstance() {
        INSTANCE = null;
    }
}

Look at the @Database annotation, we have defined the table we made earlier by calling it entities {PetrolPrice.class} you can name as any tables as you like there

VERSION is the version of the table if you alter it you need to add a new version.

exportSchema is used when you want to keep track of the database versions. Turn it off in Production yoooooooo!!!

Inside the code, we have this line inside a constructor which defines the database “Price Database” by using DatabaseBuilder method

Room.databaseBuilder(context.getApplicationContext(), FuelPriceDatabase.class, "price-database").build();

DatabaseBuilder Creates a RoomDatabase.Builder for a persistent database. Once a database is built, you should keep a reference to it and re-use it.

OKAAAY NOW LET’S GO TO THE FAMILIAR MAINACTIVITY.JAVA

What we will do there is to observe the changes in the database then do whatever you want with it

In MainActivity onCreate we have to initialize a Database instance like this

FuelPriceDatabase fuelPriceDatabase;
fuelPriceDatabase = FuelPriceDatabase.getAppDatabase(MainActivity.this);

Then we have to attach it to an observer which responds to the LiveData notification signal like this

fuelPriceDatabase.petrolPriceDao().getAllPrices().observe(this, new Observer<List<PetrolPrice>>() {
    @Override
    public void onChanged(List<PetrolPrice> petrolPriceList) {
    
        //Do whatever you want with the list here..update UI....whatever!

              }
    }
});

On the above code, I have gained an instance of Database to be able to access the DAO object that will send me to the Function that has LiveData on it. That function will check if there is any change in the specific Dao and it will emit the response which in my case is a list containing all the pricing data.

OnChanged method is called when data is changed.

THAT’S IT!!! CONGRATULATIONS, You have DONE IT!!!

Now you can update the Table from the cloud with Firebase or Manually then when you do, that Observer we have set will be fired…If its lifecycle is dead it wont…untill you go back to that screen again!! isn’t that awesome!!

TO SEE THE FULL CODE WITH UI AND ALL PLEASE GOTO MY GITHUB

Github Github https://github.com/nickyrabit/RoomWithLiveDataAndCoroutine

Instagram: nickyrabit https://www.instagram.com/nickyrabit/

Email: nicky@nickylegnard.com

Facebook: Nicholaus Legnard

LinkedIn : Nicholaus Legnard https://www.linkedin.com/in/nicholaus-legnard-5a2a89b8/

Related Posts

4 thoughts on “Android Jetpack’s Room with LiveData by Kotlin & Java

Leave a Reply

Your email address will not be published. Required fields are marked *