SQLite Made Easy : Room Persistence Library

Room persistence library introduced at Google I/O 2017 provides an abstraction layer over the SQLite database Room is a new way to create a database in your android apps, it is much similar to OrmLite. It provides enhance security, easy access, easy to setup and quick to get started with new database. All DML(Data Manipulation Language) commands are now annotated except SELECT command which works with @Query.
Room takes care of these concerns for you while providing an abstraction layer over SQLite.
1) Database
2) Entity
3) DAO

There are three major components in room:

Entity represents data for a single table row, constructed an annotated java data object. Each entity is persisted into its own table.

DAO (Data Access Object) defines the method that access the database, using annotation to bind SQL to each method.

Database is a holder class that uses annotation to define the list of entities and database version. This class content defines  the list of DAOs.



Let's implement an example to have more understanding how it works. In this example, we will create an app that allows to save user to detail e.g name , email, mobile number. you can see source code below:

a). Create a new project in android studio with empty activity.
b). Add these dependencies in module build.gradle(app).




implementation 'android.arch.persistence.room:runtime:1.0.0'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'




Define project dependencies and add Google Meven repository in root
build.gradle(project)

ext {
    buildToolsVersion = "25.0.2"    
    supportLibVersion = "25.3.1"    
    archRoomVersion = "1.0.0-alpha1"
}
allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }
    }
}


c) Now, lets create an entity called User. It defines a attributes of your table.
It must be declare one field as a Primary Key. It has property to auto generate 
values. Class is annotated with @Entity and the name of the table. To make field
primary key, you need to annotate a field with @PrimaryKey and property auto generate
which assign automatic ID's. Room will create a User table with defined attributes.

User.java

package com.sanjeev.sampleproject;

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;

/** * Created by Sanjeev on 12/27/2017. */

@Entity(tableName = "user")
public class User {
    @PrimaryKey(autoGenerate = true)
    private int id;
    @ColumnInfo(name = "name")
    private String name;
    @ColumnInfo(name = "email")
    private String email;
    @ColumnInfo(name = "number")
    private String number;

    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 getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}


d) Create a data access object using interface.This class is annotated with @DAO
annotation. Room will generate an implementation of defined methods. There are 
four annotations @Query, @Insert @Update, @Delete  to perform CRUD 
operations. @Query annotation is used to perform read operation on database.

UserDAO.java:

package com.sanjeev.sampleproject;

import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;

import java.util.List;

/** * Created by Sanjeev on 12/27/2017. */

@Dao
public interface UserDAO {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Insert    void insert(User user);

    @Delete    void delete(User user);

}




e)  Create database holder called AppDatabase extends
 RoomDatabase, we will define list of entities and 
database version. Class is annotated with 
@Database annotation. 

AppDatabase.java:

package com.sanjeev.sampleproject;

import android.arch.persistence.db.SupportSQLiteOpenHelper;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.DatabaseConfiguration;
import android.arch.persistence.room.InvalidationTracker;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;

/** * Created by Sanjeev on 12/27/2017. */

@Database(entities = {User.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {

    private static AppDatabase INSTANCE;

    public abstract UserDAO userDao();

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


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


 @Override   
 protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config) {
        return null;
    }

 @Override   
 protected InvalidationTracker createInvalidationTracker() {
        return null;
    }
}

MainActivity.java:


package com.sanjeev.sampleproject;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button buttonSave;
    private EditText edittextName, editTextEmail, editTextNumber;
    String mName, mEmail, mNumber;
    List<User> usersList=new ArrayList<>();
    AppDatabase database;
    RecyclerView recycler_view;
    UsersAdapter mAdapter;

   @Override 
   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        database=AppDatabase.getAppDatabase(this);

        initViews();
        addListners();

        usersList=database.userDao().getAll();
        setAdapter();

    }

    private void initViews() {
        buttonSave = findViewById(R.id.buttonSave);
        edittextName = findViewById(R.id.edittextName);
        editTextEmail = findViewById(R.id.editTextEmail);
        editTextNumber = findViewById(R.id.editTextNumber);
        recycler_view=findViewById(R.id.recycler_view);
    }

    private void addListners() {
        buttonSave.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.buttonSave:
                mName = edittextName.getText().toString().trim();
                mEmail = editTextEmail.getText().toString().trim();
                mNumber = editTextNumber.getText().toString().trim();
                if (mName.isEmpty()){
                    edittextName.setError("Please enter name");
                }else if (mEmail.isEmpty()){
                    editTextEmail.setError("Please enter email");

                }else if (mNumber.isEmpty()){
                    editTextNumber.setError("Please enter Mobile number");
                }else{

                    addUserInfo(database);
                    Toast.makeText(this, "Item Added", Toast.LENGTH_SHORT).show();
                    edittextName.setText("");
                    editTextEmail.setText("");
                    editTextNumber.setText("");

                }

                break;
        }
    }

    private User addUser(AppDatabase database, User user) {
        database.userDao().insert(user);
        return user;
    }

    private void addUserInfo(AppDatabase database) {
        User user = new User();
        user.setName(mName);
        user.setEmail(mEmail);
        user.setNumber(mNumber);
        usersList.add(user);
        addUser(database, user);
        mAdapter.notifyList(usersList);

    }

    private void setAdapter(){
        mAdapter = new UsersAdapter(this, usersList, new UsersAdapter.OnItemClickListener() {
            @Override            public void onItemClick(User user) {
                database.userDao().delete(user);
                usersList.remove(user);
                mAdapter.notifyDataSetChanged();

            }
        });
        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recycler_view.setLayoutManager(mLayoutManager);
        recycler_view.setItemAnimator(new DefaultItemAnimator());
        recycler_view.setAdapter(mAdapter);
    }

}

UsersAdapter.java:

package com.sanjeev.sampleproject;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/** * Created by Sanjeev on 12/27/2017. */

public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.MyViewHolder> {
    Context context;
    List<User> usersList;
    private  OnItemClickListener listener;


    public interface OnItemClickListener {
        void onItemClick(User user);
    }

    public UsersAdapter(Context context, List<User> usersList,OnItemClickListener listener) {

        this.context = context;
        this.usersList = usersList;
        this.listener=listener;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.inflater_list_items, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, final int position) {

        holder.textViewName.setText(usersList.get(position).getName());
        holder.textViewEmail.setText(usersList.get(position).getEmail());
        holder.textViewNumber.setText(usersList.get(position).getNumber());
        holder.bind(usersList.get(position),listener);

    }



    @Override
    public int getItemCount() {
        return usersList.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView textViewName,textViewEmail,textViewNumber;
        ImageView imageViewDelete;
        public MyViewHolder(View itemView) {
            super(itemView);
            textViewName=itemView.findViewById(R.id.textViewName);
            textViewEmail=itemView.findViewById(R.id.textViewEmail);
            textViewNumber=itemView.findViewById(R.id.textViewNumber);
            imageViewDelete=itemView.findViewById(R.id.imageViewDelete);
        }

        public void bind(final User user, final OnItemClickListener listener) {
        imageViewDelete.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    listener.onItemClick(user);
                }
            });
        }

    }


    public void notifyList(List<User> userList){
       this.usersList=userList;
       notifyItemInserted(userList.size());
    }

}

activity_main.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical"
tools:context="com.sanjeev.sampleproject.MainActivity">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/edittextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/editTextNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Mobile Number"/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/buttonSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SAVE"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:scrollbars="vertical"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>


inflater_list_items.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imageViewDelete"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="right"
android:src="@android:drawable/ic_delete"/>
</FrameLayout>
<TextView
android:id="@+id/textViewEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textViewNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

ScreenShots: 












 























Comments

Popular posts from this blog

Alamofire installation in XCODE