<h2><span style="color: #000080;">Android Architecture Components</span></h2>
<p><strong><span style="color: #0000ff;"><em>A new collection of libraries that help you design robust, testable, and maintainable apps.</em></span></strong><em> </em><em>—</em><em> </em><span style="color: #000080;"><em>developer.android.co</em><em>m</em></span></p>
<p>We will see three main components :</p>
<ol>
<li>Room</li>
<li>ViewModel</li>
<li>LiveData</li>
</ol>
<p>So first, let’s find out what these components actually are. Then, we’ll learn how we can use them.</p>
<p><span class="embed-youtube" style="text-align:center; display: block;"><amp-youtube data-videoid="uvoK3Lap_E0" data-param-rel="1" data-param-showsearch="0" data-param-showinfo="1" data-param-iv_load_policy="1" data-param-fs="1" data-param-hl="en-US" data-param-autohide="2" data-param-wmode="transparent" width="1200" height="675" layout="responsive"><a href="https://www.youtube.com/watch?v=uvoK3Lap_E0" placeholder><amp-img src="https://i.ytimg.com/vi/uvoK3Lap_E0/hqdefault.jpg" alt="YouTube Poster" layout="fill" object-fit="cover"><noscript><img src="https://i.ytimg.com/vi/uvoK3Lap_E0/hqdefault.jpg" loading="lazy" decoding="async" alt="YouTube Poster"></noscript></amp-img></a></amp-youtube></span></p>
<p>Get <span style="color: #0000ff;"><strong>Source code</strong></span> From <span style="color: #00ff00;"><a style="color: #00ff00;" href="https://github.com/arunk7839/AndroidRoomExample"><strong>HERE</strong></a></span>.</p>
<p>By creating an <strong><span style="color: #000080;">E</span><span style="color: #000080;">vent app</span></strong> I will demonstrate you the working of <span style="color: #000000;">Android Architecture Components</span><strong>  <span style="color: #0000ff;">Room, ViewModel, LiveData.</span></strong></p>
<p> ;</p>
<p><img class="aligncenter wp-image-575 size-large" src="https://c1ctech.com/wp-content/uploads/2018/05/Screenshot_1530085640-576x1024.png" alt="" width="576" height="1024" /></p>
<h3><span style="color: #000080;">Room Persistence Library</span></h3>
<p>Major problem with <span style="color: #0000ff;"><strong>SQLite</strong></span> usage is</p>
<ul>
<li>There is no <span style="color: #0000ff;"><strong>compile-time</strong></span> verification of raw SQL queries.For example if you write a SQL query with a wrong <span style="color: #0000ff;"><strong>column name</strong></span> that does not exist in real database then it will give exception during run time and you can not capture this issue during <span style="color: #0000ff;"><strong>compile time</strong></span>.</li>
</ul>
<p> ;</p>
<ul>
<li>As your schema changes you need to <span style="color: #0000ff;"><strong>update</strong></span> the affected SQL queries manually. This process can be time consuming and error prone.</li>
</ul>
<p> ;</p>
<ul>
<li>You need to use lots of<span style="color: #0000ff;"> <strong>boilerplate code</strong></span> to convert between SQL queries and Java data objects.</li>
</ul>
<p> ;</p>
<p><span style="color: #0000ff;"><strong>Room takes care of these concerns for you while providing an abstraction layer over SQLite.</strong></span></p>
<p><span style="color: #000080;"><strong>There are three major components in Room:</strong></span></p>
<p><span style="color: #000080;"><strong>Entity</strong> :</span> A class annotated with the <span style="color: #0000ff;"><strong>@Entity</strong><a style="color: #0000ff;" href="https://developer.android.com/reference/android/arch/persistence/room/Entity.html"> </a></span> annotation is mapped to a table in database. Every entity is persisted in its own table and every field in class represents the column name.</p>
<ul>
<li><span style="color: #0000ff;"><strong>tableName</strong></span> attribute is used to define the name of the table</li>
<li>Every entity class must have at-least one <span style="color: #0000ff;"><strong>Primary Key</strong></span> field, annotated with<span style="color: #0000ff;"> <strong>@PrimaryKey</strong></span></li>
<li>Fields in entity class can be annotated with <span style="color: #0000ff;"><strong>@ColumnInfo</strong></span>(name = “name_of_column”) annotation to give specific column names</li>
<li id="f6c7" class="graf graf--li graf-after--li">If you don’t want to include some field for the table but want to keep it in your model class than annotate those field with @Ignore</li>
<li id="b3a7" class="graf graf--li graf-after--li">If you want your data to get stored in some other format than that of the type of variable you defined in your model class than create another class add your conversion logic there and annotate those methods with <span style="color: #0000ff;"><strong class="markup--strong markup--li-strong"><em class="markup--em markup--li-em">@TypeConverter</em></strong> </span>than add that class to your database class using annotation <span style="color: #0000ff;"><strong class="markup--strong markup--li-strong"><em class="markup--em markup--li-em">@TypeConverters.</em></strong></span></li>
</ul>
<p> ;</p>
<pre>@Entity(tableName = TABLE_NAME)
public class Event {


 public static final String TABLE_NAME = "events";


 @PrimaryKey(autoGenerate = true)
 private int id;

 private String title;
 private String description;

 @TypeConverters(DateConverter.class)
 private Date date;

 public Event() {

 }

 @Ignore
 public Event(int id, String title, String description) {
 this.id = id;
 this.title = title;
 this.description = description;
 this.date = date;
 }

 public int getId() {
 return id;
 }

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


 public void setTitle(String title) {
 this.title = title;
 }

 public Date getDate() {
 return date;
 }

 public void setDate(Date date) {
 this.date = date;
 }

 public void setDescription(String description) {
 this.description = description;
 }

 public String getDescription() {
 return description;
 }

 public String getTitle() {
 return title;
 }

</pre>
<p><strong> <span style="color: #000080;">DAO</span></strong><span style="color: #000080;"> : </span><span style="color: #0000ff;"><strong>Data Access Object</strong></span> is either be an interface or an abstract class annotated with<span style="color: #0000ff;"> <strong>@Doa</strong></span> annotation, containing all the methods to define the operations to be performed on data. The methods can be annotated with</p>
<ul>
<li><strong><a href="https://developer.android.com/reference/android/arch/persistence/room/Query.html">@Query </a> </strong>to retrieve data from database</li>
<li><a href="https://developer.android.com/reference/android/arch/persistence/room/Insert.html"><strong>@Insert</strong> </a> to insert data into database</li>
<li><a href="https://developer.android.com/reference/android/arch/persistence/room/Delete.html"><strong>@Delete</strong> </a> to delete data from database</li>
<li><a href="https://developer.android.com/reference/android/arch/persistence/room/Update.html"><strong>@Update</strong> </a> to update data in database</li>
</ul>
<p><span style="color: #000080;"><strong>Note</strong><strong>:</strong></span>The result of SQLite queries are composed into <span style="color: #0000ff;"><strong>cursor</strong></span> object, DAO methods abstract the conversion of cursor to <span style="color: #0000ff;"><strong>Entity objects and vice-versa.</strong></span></p>
<pre>@Dao
public interface EventDao {

 @Query("SELECT * FROM " + Event.TABLE_NAME)
 LiveData<;List<;Event>;>; getEvents();

 @Insert(onConflict = REPLACE)
 void addEvent(Event event);

 @Delete
 void deleteEvent(Event event);

 @Update(onConflict = REPLACE)
 void updateEvent(Event event);

}</pre>
<p>In case there are conflicts during such manipulation operations, we have to specify a conflict strategy too. In our example, we are using <span style="color: #0000ff;"><strong class="markup--strong markup--p-strong">REPLACE</strong></span>. It means that the conflicting entry will be replaced by the current entry.</p>
<p><span style="color: #000080;"><strong>Database</strong><strong> :</strong> </span>Database is a container for tables. An abstract class annotated with <a href="https://developer.android.com/reference/android/arch/persistence/room/Database.html"><strong>@Database</strong> </a> annotation is used to create a database with given name along with database version.</p>
<ul>
<li><span style="color: #0000ff;"><strong>version</strong></span> = intValueForDBVersion is used to define the database version</li>
<li><span style="color: #0000ff;"><strong>entities</strong> </span>= {EntityClassOne.class, &#8230;.} is used to define list of entities for database</li>
</ul>
<p> ;</p>
<pre>@Database(entities = {Event.class}, version = 1)
public abstract class EventDatabase extends RoomDatabase {
 private static final String DB_NAME = "Event_Database.db";
 private static EventDatabase INSTANCE;


 public static EventDatabase getEventDatabase(Context context) {
 if (INSTANCE == null) {
 INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();

 }
 return INSTANCE;
 }

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

 public abstract EventDao eventDao();
}</pre>
<h3><strong><span style="color: #000080;">ViewModel</span></strong></h3>
<p>The <a href="https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html" data-href="https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html"><strong>ViewModel</strong></a> class is designed to hold and manage UI-related data in a life-cycle conscious way. This allows data to survive configuration changes such as screen rotations.</p>
<p>Previously, you might have used <strong><a href="https://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance%28%29" data-href="https://developer.android.com/reference/android/app/Activity.html#onRetainNonConfigurationInstance()">onRetainNonConfigurationInstance</a></strong> to save this data during a configuration change and unpack it on the other end.</p>
<p>The ViewModel exists when you first request a ViewModel (usually in the onCreate the Activity) until the Activity is finished and destroyed. onCreate may be called several times during the life of an Activity, such as when the app is rotated, but the ViewModel survives throughout.</p>
<p><span style="color: #000080;"><strong>There are two steps to setting up and using a ViewModel:</strong></span></p>
<p><strong><span style="color: #0000ff;">Step 1: Create a ViewModel class</span></strong></p>
<pre>public class EventViewModel extends AndroidViewModel {

 private EventDatabase eventDatabase;

 private LiveData<;List<;Event>;>; eventList;

 public EventViewModel(@NonNull Application application) {
 super(application);

 eventDatabase = EventDatabase.getEventDatabase(this.getApplication());

 eventList = eventDatabase.eventDao().getEvents();
 }

 public LiveData<;List<;Event>;>; getEventList() {
 return eventList;
 }

 public EventDatabase getEventDatabase() {
 return eventDatabase;
 }

}</pre>
<p><strong><span style="color: #0000ff;">Step 2: Set up communications between your ViewModel and your UI controller and </span><span style="color: #0000ff;">Use the ViewModel in your UI Controller.</span></strong></p>
<pre>private EventDatabase eventDatabase;
private EventViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 
 viewModel = ViewModelProviders.of(this).get(EventViewModel.class);

 eventDatabase = viewModel.getEventDatabase();

 viewModel.getEventList();

</pre>
<p>The first time the <strong><span style="color: #008000;"><span style="color: #0000ff;"><a style="color: #0000ff;" href="https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders.html#of%28android.support.v4.app.Fragment%29" data-href="https://developer.android.com/reference/android/arch/lifecycle/ViewModelProviders.html#of(android.support.v4.app.Fragment)">ViewModelProviders.of</a></span> </span></strong>method is called by MainActivity, it creates a new ViewModel instance. When this method is called again, which happens whenever onCreate is called, it will return the pre-existing ViewModel associated with the specific MainActivity. This is what preserves the data.</p>
<h3><span style="color: #000080;">LiveData</span></h3>
<p><span style="color: #0000ff;"><a style="color: #0000ff;" href="https://developer.android.com/topic/libraries/architecture/livedata.html"><strong>LiveData</strong></a></span> is an observable lifecycle-aware data holder class. Your UI code subscribes to changes in the underlying data, tied into a <a href="https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html"><strong>LifecycleOwner</strong></a>, and LiveData makes sure the observer:</p>
<ul>
<li>Gets updates to the data while the Lifecycle is in an active state (<span style="color: #0000ff;">STARTED or RESUMED</span>)</li>
<li>Is removed when the <a href="https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html"><strong>LifecycleOwner </strong></a>is destroyed</li>
<li>Gets up-to-date data when the <a href="https://developer.android.com/reference/android/arch/lifecycle/LifecycleOwner.html"><strong>LifecycleOwner</strong></a>restarts due to a configuration change or is restarted from the back stack</li>
</ul>
<p id="create_livedata_objects"><strong><span style="color: #000080;">Create LiveData objects</span></strong></p>
<p>Inside Room DAO I have defined List<;Event>; as LiveData object.</p>
<pre>@Query("SELECT * FROM " + Event.TABLE_NAME)
LiveData<;List<;Event>;>; getEvents();
</pre>
<p id="observe_livedata_objects"><strong><span style="color: #000080;">Observe LiveData objects</span></strong></p>
<pre>viewModel.getEventList().observe(this, new Observer<;List<;Event>;>;() {
 @Override
 public void onChanged(@Nullable List<;Event>; eventList) {
 events = eventList;

 adapter = new EventsAdapter(events, getApplicationContext());

 recyclerView.setAdapter(adapter);

 checkListEmptyOrNot();
 }
});</pre>
<p>Whenever there is a change in the data, the <span style="color: #0000ff;"><strong>onChanged()</strong></span> callback is executed and we get the new data.We can update the UI accordingly.</p>
<h3><span style="color: #000080;">Creating New Project</span></h3>
<p>1.In Android Studio, go to <span style="color: #0000ff;"><strong>File </strong><strong>⇒</strong><strong> New Project</strong></span> and fill all the details required to create a new project. When it prompts to select a default activity, select <span style="color: #0000ff;"><strong>Blank Activity</strong></span> and proceed.</p>
<p>2.Open <span style="color: #0000ff;"><strong>build.gradle</strong></span> and add <strong><span style="color: #008000;">Room ,Livedata,Viewmodel</span> </strong>dependency and rebuild the project..</p>
<p><span style="color: #000080;"><strong>Build.gradle</strong></span></p>
<pre>dependencies {
 
 <span style="color: #008000;"><strong>//recyclerview</strong></span>
 compile 'com.android.support:recyclerview-v7:26.1.0'

 <span style="color: #008000;"><strong>//room library</strong></span>
 compile 'android.arch.persistence.room:runtime:1.0.0'
 annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'

 <strong><span style="color: #008000;">//livedata and viewmodel</span></strong>
 compile 'android.arch.lifecycle:extensions:1.0.0'

 
}</pre>
<p>3. For Room we will create the model,Data Access Object and the Database.</p>
<h3 id="8429" class="graf graf--h3 graf-after--figure"><strong><span style="color: #000080;">Creating the Model</span></strong></h3>
<p><span style="color: #0000ff;"><strong>Event.Java<br />
</strong></span></p>
<pre>package com.example.lenovo.eventapp.entity;

import android.arch.persistence.room.Entity;
import android.arch.persistence.room.Ignore;
import android.arch.persistence.room.PrimaryKey;
import android.arch.persistence.room.TypeConverters;

import com.example.lenovo.eventapp.db.DateConverter;

import java.util.Date;

import static com.example.lenovo.eventapp.entity.Event.TABLE_NAME;


@Entity(tableName = TABLE_NAME)
public class Event {


 public static final String TABLE_NAME = "events";


 @PrimaryKey(autoGenerate = true)
 private int id;

 private String title;
 private String description;
 @TypeConverters(DateConverter.class)
 private Date date;

 public Event() {

 }

 @Ignore
 public Event(int id, String title, String description) {
 this.id = id;
 this.title = title;
 this.description = description;
 this.date = date;
 }

 public int getId() {
 return id;
 }

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


 public void setTitle(String title) {
 this.title = title;
 }

 public Date getDate() {
 return date;
 }

 public void setDate(Date date) {
 this.date = date;
 }

 public void setDescription(String description) {
 this.description = description;
 }

 public String getDescription() {
 return description;
 }

 public String getTitle() {
 return title;
 }


 @Override
 public String toString() {
 return "Event{" +
 "id=" + id +
 ", name='" + title + '\'' +
 ", description='" + description + '\'' +
 ", date='" + date + '\'' +
 '}';
 }

}
</pre>
<h3 id="3cae" class="graf graf--h4 graf-after--p"><span style="color: #000080;"><strong>Data Access Object</strong></span></h3>
<p><strong><span style="color: #0000ff;">EventDao.Java</span></strong></p>
<pre>package com.example.lenovo.eventapp.dao;

import android.arch.lifecycle.LiveData;
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 android.arch.persistence.room.Update;

import com.example.lenovo.eventapp.entity.Event;

import java.util.List;

import static android.arch.persistence.room.OnConflictStrategy.REPLACE;


@Dao
public interface EventDao {

 @Query("SELECT * FROM " + Event.TABLE_NAME)
 LiveData<;List<;Event>;>; getEvents();

 @Insert(onConflict = REPLACE)
 void addEvent(Event event);

 @Delete
 void deleteEvent(Event event);

 @Update(onConflict = REPLACE)
 void updateEvent(Event event);

}

</pre>
<h3 id="003d" class="graf graf--h4 graf-after--p"><span style="color: #000080;"><strong>Creating the database</strong></span></h3>
<p><strong><span style="color: #0000ff;">EventDatabase.Java<br />
</span></strong></p>
<pre>package com.example.lenovo.eventapp.db;

import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;

import com.example.lenovo.eventapp.dao.EventDao;
import com.example.lenovo.eventapp.entity.Event;


@Database(entities = {Event.class}, version = 1)
public abstract class EventDatabase extends RoomDatabase {
 private static final String DB_NAME = "Event_Database.db";
 private static EventDatabase INSTANCE;


 public static EventDatabase getEventDatabase(Context context) {
 if (INSTANCE == null) {
 INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();

 }
 return INSTANCE;
 }

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

 public abstract EventDao eventDao();
}

</pre>
<p>4. SQL cannot store data types like <strong><span style="color: #0000ff;">Date</span></strong> by default. That’s why we need a way to convert it into a compatible data type to store it in the database. We use the <strong><span style="color: #0000ff;">@TypeConverters</span></strong> to specify the converter for the date attribute. So to help us with this conversion, we’ll create a class called <strong><span style="color: #0000ff;"><em class="markup--em markup--p-em">DateConverter</em></span></strong>.</p>
<p><span style="color: #0000ff;"><strong>DateConverter.Java</strong></span></p>
<pre>package com.example.lenovo.eventapp.db;

import android.arch.persistence.room.TypeConverter;

import java.util.Date;

public class DateConverter {

 @TypeConverter
 public static Date toDate(Long timestamp) {
 return timestamp == null ? null : new Date(timestamp);
 }

 @TypeConverter
 public static Long toTimestamp(Date date) {
 return date == null ? null : date.getTime();
 }
}</pre>
<p>5. Open activity_main layout and write the below code.</p>
<p><strong><span style="color: #0000ff;">activity_main.xml</span></strong></p>
<pre><;?xml version="1.0" encoding="utf-8"?>;
<;android.support.constraint.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">;

 <;android.support.v7.widget.RecyclerView
 android:id="@+id/recycler_view_list_events"
 android:layout_width="0dp"
 android:layout_height="0dp"
 app:layout_constraintBottom_toBottomOf="parent"
 app:layout_constraintLeft_toLeftOf="parent"
 app:layout_constraintRight_toRightOf="parent"
 app:layout_constraintTop_toTopOf="parent">;

 <;/android.support.v7.widget.RecyclerView>;

 <;TextView
 android:id="@+id/tv_no_events_found"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:fontFamily="sans-serif"
 android:gravity="center"
 android:text="NO EVENTS FOUND!"
 android:textColor="@color/colorPrimaryDark"
 android:textSize="25sp"
 android:visibility="gone" />;

 <;android.support.design.widget.FloatingActionButton
 android:id="@+id/fab_add"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginBottom="16dp"
 android:layout_marginRight="16dp"
 app:elevation="4dp"
 app:layout_constraintBottom_toBottomOf="parent"
 app:layout_constraintRight_toRightOf="parent"
 app:srcCompat="@drawable/ic_add_black_24dp" />;
<;/android.support.constraint.ConstraintLayout>;</pre>
<p>6. Open <strong><span style="color: #0000ff;">event_dialog.xml</span></strong> and write the below code.Here this layout represents the view set up for alertdialog.</p>
<p><strong><span style="color: #0000ff;">event_dialog.xml</span></strong></p>
<!-- WP QUADS Content Ad Plugin v. 2.0.98.1 -->
<div class="quads-location quads-ad2" id="quads-ad2" style="float:none;margin:0px;">

</div>

<pre><;?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="match_parent"
 android:orientation="vertical"
 android:padding="8dp">;

 <;TextView
 android:id="@+id/dialog_title"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginBottom="10dp"
 android:fontFamily="sans-serif-medium"
 android:text="New Event"
 android:textColor="@color/colorAccent"
 android:textSize="22sp"
 android:textStyle="normal" />;

 <;EditText
 android:id="@+id/edt_title"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@android:color/transparent"
 android:fontFamily="sans-serif"
 android:gravity="top"
 android:hint="Title"
 android:inputType="textCapSentences|textMultiLine"
 android:lines="2"
 android:textColor="@android:color/black"
 android:textColorHint="@color/colorPrimaryDark"
 android:textSize="18sp" />;

 <;EditText
 android:id="@+id/edt_discription"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@android:color/transparent"
 android:fontFamily="sans-serif"
 android:gravity="top"
 android:hint="Discription"
 android:inputType="textCapSentences|textMultiLine"
 android:lines="3"
 android:textColor="@android:color/black"
 android:textColorHint="@color/colorPrimaryDark"
 android:textSize="18sp" />;

 <;RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content">;

 <;TextView
 android:id="@+id/tv_date"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentLeft="true"
 android:layout_marginLeft="8dp"
 android:fontFamily="sans-serif"
 android:textColor="@android:color/black"
 android:textSize="18sp" />;

 <;Button
 android:id="@+id/btn_setdate"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentRight="true"
 android:background="@color/colorAccent"
 android:text="set"
 android:textColor="@android:color/white"
 android:textStyle="bold" />;

 <;/RelativeLayout>;
<;/LinearLayout>;</pre>
<p>7. Open <strong><span style="color: #0000ff;">list_item_event.xml</span></strong> and write the below code.Here this layout represents the recyclerview list item.</p>
<p><strong><span style="color: #0000ff;"> list_item_event.xml</span></strong></p>
<pre><;?xml version="1.0" encoding="utf-8"?>;
<;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="8dp"
 android:padding="8dp">;

 <;LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentLeft="true"
 android:orientation="vertical">;

 <;TextView
 android:id="@+id/tv_title"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:fontFamily="sans-serif"
 android:textColor="@android:color/holo_orange_dark"
 android:textSize="20dp"
 android:textStyle="bold" />;

 <;TextView
 android:id="@+id/tv_discription"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginTop="6dp"
 android:fontFamily="sans-serif"
 android:textColor="@android:color/holo_green_light"
 android:textSize="16dp" />;
 <;/LinearLayout>;


 <;TextView
 android:id="@+id/tv_timestamp"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_alignParentRight="true"
 android:fontFamily="sans-serif"
 android:textColor="@color/colorAccent"
 android:textSize="16dp"
 android:textStyle="bold" />;


<;/RelativeLayout>;</pre>
<p>8. Now since we will be displaying a list of items, we need a <span style="color: #0000ff;"><strong>RecyclerView</strong></span>. So first, let’s create an adapter.</p>
<p><strong><span style="color: #0000ff;">EventsAdapter.Java</span></strong></p>
<pre>package com.example.lenovo.eventapp;

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.TextView;

import com.example.lenovo.eventapp.entity.Event;

import java.util.List;

public class EventsAdapter extends RecyclerView.Adapter<;EventsAdapter.EventViewHolder>; {
 private final Context context;
 private List<;Event>; items;


 public EventsAdapter(List<;Event>; items, Context context) {
 this.items = items;
 this.context = context;

 }

 public class EventViewHolder extends RecyclerView.ViewHolder {
 TextView titleTextView;
 TextView dateTextView;
 TextView descriptionTextView;

 EventViewHolder(View v) {
 super(v);
 titleTextView = (TextView) v.findViewById(R.id.tv_title);
 dateTextView = (TextView) v.findViewById(R.id.tv_timestamp);
 descriptionTextView = (TextView) v.findViewById(R.id.tv_discription);

 }
 }

 @Override
 public EventViewHolder onCreateViewHolder(ViewGroup parent,
 int viewType) {
 View v = LayoutInflater.from(context)
 .inflate(R.layout.list_item_event, parent, false);

 return new EventViewHolder(v);
 }

 @Override
 public void onBindViewHolder(EventViewHolder holder, int position) {
 Event item = items.get(position);
 holder.titleTextView.setText(item.getTitle());
 holder.descriptionTextView.setText(item.getDescription());
 holder.dateTextView.setText(item.getDate().toLocaleString().substring(0, 12));
 }


 @Override
 public int getItemCount() {

 return items.size();
 }


}</pre>
<p>9. For recyclerview I have created custom <strong><span style="color: #0000ff;">onitemclicklistener</span></strong> and the code is given below.</p>
<p><strong><span style="color: #0000ff;">RecyclerTouchListener.Java<br />
</span></strong></p>
<pre>package com.example.lenovo.eventapp;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

 private ClickListener clicklistener;
 private GestureDetector gestureDetector;

 public RecyclerTouchListener(Context context, final RecyclerView recycleView, final ClickListener clicklistener) {

 this.clicklistener = clicklistener;
 gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
 @Override
 public boolean onSingleTapUp(MotionEvent e) {
 return true;
 }

 @Override
 public void onLongPress(MotionEvent e) {
 View child = recycleView.findChildViewUnder(e.getX(), e.getY());
 if (child != null &;&; clicklistener != null) {
 clicklistener.onLongClick(child, recycleView.getChildAdapterPosition(child));
 }
 }
 });
 }

 @Override
 public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
 View child = rv.findChildViewUnder(e.getX(), e.getY());
 if (child != null &;&; clicklistener != null &;&; gestureDetector.onTouchEvent(e)) {
 clicklistener.onClick(child, rv.getChildAdapterPosition(child));
 }

 return false;
 }

 @Override
 public void onTouchEvent(RecyclerView rv, MotionEvent e) {

 }

 @Override
 public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

 }

 public interface ClickListener {
 void onClick(View view, int position);

 void onLongClick(View view, int position);
 }
}

</pre>
<h3><span style="color: #000080;"><strong>Create the AndroidViewModel</strong></span></h3>
<p><span style="color: #0000ff;"><strong>EventViewModel.Java</strong></span></p>
<pre>package com.example.lenovo.eventapp;

import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import com.example.lenovo.eventapp.db.EventDatabase;
import com.example.lenovo.eventapp.entity.Event;
import java.util.List;

public class EventViewModel extends AndroidViewModel {

 private EventDatabase eventDatabase;

 private LiveData<;List<;Event>;>; eventList;

 public EventViewModel(@NonNull Application application) {
 super(application);

 eventDatabase = EventDatabase.getEventDatabase(this.getApplication());

 eventList = eventDatabase.eventDao().getEvents();
 }

 public LiveData<;List<;Event>;>; getEventList() {
 return eventList;
 }

 public EventDatabase getEventDatabase() {
 return eventDatabase;
 }

}</pre>
<p>10. Now create <strong><span style="color: #0000ff;">MainActivity.Java</span></strong> that extends <strong><span style="color: #0000ff;">AppCompatActivity</span></strong> to display a list of events.</p>
<p><strong><span style="color: #0000ff;">MainActivity.Java</span></strong></p>
<pre>package com.example.lenovo.eventapp;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
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.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.lenovo.eventapp.db.EventDatabase;
import com.example.lenovo.eventapp.entity.Event;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


public class MainActivity extends AppCompatActivity implements DatePickerDialog.OnDateSetListener {

 private RecyclerView recyclerView;
 private Date date;
 private DatePickerDialog datePickerDialog;
 private Calendar calendar;
 private EventDatabase eventDatabase;
 private EventViewModel viewModel;
 private TextView noEventsFound;
 private FloatingActionButton fab;
 private EventsAdapter adapter;
 private List<;Event>; events = new ArrayList<;>;();
 private TextView tv_date;

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

 calendar = Calendar.getInstance();

 datePickerDialog = new DatePickerDialog(this, this, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));

 viewModel = ViewModelProviders.of(this).get(EventViewModel.class);

 eventDatabase = viewModel.getEventDatabase();

 noEventsFound = (TextView) findViewById(R.id.tv_no_events_found);

 recyclerView = (RecyclerView) findViewById(R.id.recycler_view_list_events);

 recyclerView.setItemAnimator(new DefaultItemAnimator());

 recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));


 viewModel.getEventList().observe(this, new Observer<;List<;Event>;>;() {
 @Override
 public void onChanged(@Nullable List<;Event>; eventList) {
 events = eventList;

 adapter = new EventsAdapter(events, getApplicationContext());

 recyclerView.setAdapter(adapter);

 checkListEmptyOrNot();
 }
 });

 <strong><span style="color: #008000;">//shows NO EVENTS FOUND when list is empty</span></strong>
 checkListEmptyOrNot();

 recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), recyclerView, new RecyclerTouchListener.ClickListener() {
 @Override
 public void onClick(View view, int position) {

 }

 @Override
 public void onLongClick(View view, int position) {

 <span style="color: #008000;"><strong>//show Alertdialog to edit or update the event</strong></span>
 showActionsDialog(position);
 }
 }));

 <strong><span style="color: #008000;">//add listener on FloatingActionButton to add event</span></strong>
 fab = (FloatingActionButton) findViewById(R.id.fab_add);

 fab.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {

 <strong><span style="color: #008000;">//adding new event</span></strong>
 showEventDialog(false, null, -1);
 }
 });
 }

 private class DatabaseAsync extends AsyncTask<;Object, Void, Void>; {

 private EventDatabase db;

 DatabaseAsync(EventDatabase eventDatabase) {
 db = eventDatabase;
 }

 @Override
 protected Void doInBackground(Object... params) {

 Boolean shouldUpdate = (Boolean) params[0];
 int position = (int) params[1];
 String title = (String) params[2];
 String detail = (String) params[3];
 Date date = (Date) params[4];

 <strong><span style="color: #008000;">//check whether to add add or update event</span></strong>
 if (shouldUpdate != null) {
 <span style="color: #008000;"><strong>//update event</strong></span>
 if (shouldUpdate) {
 Event event = events.get(position);
 event.setTitle(title);
 event.setDescription(detail);
 event.setDate(date);

 <strong><span style="color: #008000;">//update event into the database</span></strong>
 db.eventDao().updateEvent(event);


 } else {
 <strong><span style="color: #008000;">//add event</span></strong>
 Event event = new Event();
 event.setTitle(title);
 event.setDescription(detail);
 event.setDate(date);

 <strong><span style="color: #008000;">//add event into the database</span></strong>
 db.eventDao().addEvent(event);
 }

 } else {
 <strong><span style="color: #008000;">//delete event</span></strong>
 if (position != -1) {
 Event event = events.get(position);

 <strong><span style="color: #008000;">//delete event from database</span></strong>
 db.eventDao().deleteEvent(event);
 }
 }
 return null;

 }
 }

 private void showActionsDialog(final int position) {
 CharSequence colors[] = new CharSequence[]{"Edit", "Delete"};

 AlertDialog.Builder builder = new AlertDialog.Builder(this);
 builder.setTitle("Choose option");
 builder.setItems(colors, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 if (which == 0) {

 <strong><span style="color: #008000;">//show Alertdialog to update the event</span></strong>
 showEventDialog(true, events.get(position), position);
 } else {

 <strong><span style="color: #008000;">//delete event from database</span></strong>
 deleteEvent(position);
 }
 }
 });
 builder.show();
 }

 private void deleteEvent(int position) {

 new DatabaseAsync(eventDatabase).execute(null, position, null, null, null);
 }

 private void showEventDialog(final Boolean shouldUpdate, final Event event, final int position) {

 LayoutInflater layoutInflater = LayoutInflater.from(getApplicationContext());
 View view = layoutInflater.inflate(R.layout.event_dialog, null);

 AlertDialog.Builder alertDialogBuilderUserInput = new AlertDialog.Builder(this);
 alertDialogBuilderUserInput.setView(view);

 TextView dialog_title = (TextView) view.findViewById(R.id.dialog_title);

 final EditText edt_title = (EditText) view.findViewById(R.id.edt_title);

 final EditText edt_discription = (EditText) view.findViewById(R.id.edt_discription);

 tv_date = (TextView) view.findViewById(R.id.tv_date);

 Button btn_setdate = (Button) view.findViewById(R.id.btn_setdate);

 <strong><span style="color: #008000;">//add listener to button to open datepickerdialog</span></strong>
 btn_setdate.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {

 <strong><span style="color: #008000;">//open datepickerdialog</span></strong>
 datePickerDialog.show();
 }
 });

 dialog_title.setText(!shouldUpdate ? "New Event" : "Edit Event");

 <strong><span style="color: #008000;">//in case of update we want all the
 //fields to be set bydefault with text</span></strong>
 if (shouldUpdate &;&; event != null) {
 edt_title.setText(event.getTitle());
 edt_discription.setText(event.getDescription());
 tv_date.setText(event.getDate().toLocaleString().substring(0, 11));
 }

 alertDialogBuilderUserInput
 .setCancelable(false)
 .setPositiveButton(shouldUpdate ? "update" : "add", new DialogInterface.OnClickListener() {
 public void onClick(DialogInterface dialogBox, int id) {

 }
 })
 .setNegativeButton("cancel",
 new DialogInterface.OnClickListener() {
 public void onClick(DialogInterface dialogBox, int id) {
 dialogBox.cancel();
 }
 });

 final AlertDialog alertDialog = alertDialogBuilderUserInput.create();

 alertDialog.show();

 alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {

 <strong><span style="color: #008000;">// Show toast message when no text is entered</span></strong>
 if (TextUtils.isEmpty(edt_title.getText().toString()) &;&; !TextUtils.isEmpty(edt_discription.getText().toString())) {
 Toast.makeText(MainActivity.this, "Enter title!", Toast.LENGTH_SHORT).show();
 } else if (!TextUtils.isEmpty(edt_title.getText().toString()) &;&; TextUtils.isEmpty(edt_discription.getText().toString())) {
 Toast.makeText(MainActivity.this, "Enter description!", Toast.LENGTH_SHORT).show();
 } else if (TextUtils.isEmpty(edt_title.getText().toString()) &;&; TextUtils.isEmpty(edt_discription.getText().toString())) {
 Toast.makeText(MainActivity.this, "Enter title and description!", Toast.LENGTH_SHORT).show();
 } else {
 alertDialog.dismiss();
 }

 <strong><span style="color: #008000;">//Update or add data into the database only when both field are filled(i.e title,description)</span></strong>
 if (!TextUtils.isEmpty(edt_title.getText().toString()) &;&; !TextUtils.isEmpty(edt_discription.getText().toString())) {

 <strong><span style="color: #008000;">// check if user updating note</span></strong>

 if (shouldUpdate &;&; event != null) {
 <strong><span style="color: #008000;">// update event</span></strong>
 new DatabaseAsync(eventDatabase).execute(shouldUpdate, position, edt_title.getText().toString(), edt_discription.getText().toString(), date);


 } else {
 <strong><span style="color: #008000;">// create new event</span></strong>
 new DatabaseAsync(eventDatabase).execute(shouldUpdate, -1, edt_title.getText().toString(), edt_discription.getText().toString(), date);


 }
 }
 }
 });


 }

 @Override
 public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
 calendar.set(Calendar.YEAR, year);
 calendar.set(Calendar.MONTH, month);
 calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
 date = calendar.getTime();
 tv_date.setText(date.toLocaleString().substring(0, 12));

 }


 public void checkListEmptyOrNot() {
 if (events.isEmpty())
 noEventsFound.setVisibility(View.VISIBLE);
 else
 noEventsFound.setVisibility(View.GONE);
 }


}</pre>
<p><span style="color: #000080;"><strong><br />
When you run the app it will look like this:</strong></span></p>
<p><img class="alignnone size-medium wp-image-572" src="https://c1ctech.com/wp-content/uploads/2018/05/Screenshot_1530085350-169x300.png" alt="" width="169" height="300" /> <img class="alignnone size-medium wp-image-573" src="https://c1ctech.com/wp-content/uploads/2018/05/Screenshot_1530085371-169x300.png" alt="" width="169" height="300" /> <img class="alignnone size-medium wp-image-574" src="https://c1ctech.com/wp-content/uploads/2018/05/Screenshot_1530085392-169x300.png" alt="" width="169" height="300" /></p>
<p> ;</p>
<p><span style="color: #000080;"><strong>Related posts:</strong></span></p>
<ul>
<li><a href="https://c1ctech.com/a-simple-basic-example-of-viewmodel/"><strong><span style="color: #008000;">A Simple Basic Example of ViewModel</span></strong></a></li>
<li><a href="https://c1ctech.com/android-room-persistence-library-example/"><span style="color: #008000;"><strong>Android Room Persistence Library Example</strong></span></a></li>
</ul>


