Room Persistence Library
Major problem with SQLite usage is
- There is no compile-time verification of raw SQL queries.For example if you write a SQL query with a wrong column name that does not exist in real database then it will give exception during run time and you can not capture this issue during compile time.
- As your schema changes you need to update the affected SQL queries manually. This process can be time consuming and error prone.
- You need to use lots of boilerplate code to convert between SQL queries and Java data objects.
Room takes care of these concerns for you while providing an abstraction layer over SQLite.
By creating an event app i will demonstrate you the working of insert, update, delete and retrieve functionality using the Room database.Get GITHUB code from HERE.
There are three major components in Room:
Entity : A class annotated with the @Entity 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.
- tableName attribute is used to define the name of the table
- Every entity class must have at-least one Primary Key field, annotated with @PrimaryKey
- Fields in entity class can be annotated with @ColumnInfo(name = “name_of_column”) annotation to give specific column names
DAO : Data Access Object is either be an interface or an abstract class annotated with @Doa annotation, containing all the methods to define the operations to be performed on data. The methods can be annotated with
- @Query to retrieve data from database
- @Insert to insert data into database
- @Delete to delete data from database
- @Update to update data in database
Note:The result of SQLite queries are composed into cursor object, DAO methods abstract the conversion of cursor to Entity objects and vice-versa.
Database : Database is a container for tables. An abstract class annotated with @Database annotation is used to create a database with given name along with database version.
- version = intValueForDBVersion is used to define the database version
- entities = {EntityClassOne.class, ….} is used to define list of entities for database
Building an Event App
We will build a Event App that will allow the user to:
- Create and Save event in database
- Display a list of events
- Update and Delete event
Creating New Project
1.In Android Studio, go to File ⇒ New Project and fill all the details required to create a new project. When it prompts to select a default activity, select Blank Activity and proceed.
2.Open build.gradle (Module:app) and add room library dependency.
dependencies { implementation 'com.android.support:support-v4:26.1.0' compile 'com.android.support:design:26.1.0' //room dependency compile 'android.arch.persistence.room:runtime:1.0.0' annotationProcessor 'android.arch.persistence.room:compiler:1.0.0' //recyclerview dependency compile 'com.android.support:recyclerview-v7:26.1.0' }
Create Entity
3. Before creating a database, Let’s create an Entity, named as Event and later, Objects of this class will be added to database.
To do this:
- Create a class named Event.
- Add @Entity annotation on the class.
- Add ID, title,description and date fields.
- Important: mark at least one field with @PrimaryKey annotation.
- Use alt+insert to implement constructor, override getter and setter, and optionally override equals or toString.
Event.Java
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 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; private String 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 String getDate() { return date; } public void setDate(String date) { this.date = date; } public void setTitle(String title) { this.title = title; } 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 + '\'' + '}'; } }
Creating DAO
4. DAOs define all methods to access database, annotated with @Dao annotation. The DAO perform CRUD operations on data within a database.
The following code will:
- Create an interface, marked with @Dao annotation.
- Add methods for CRUD operations.
EventDao.Java
package com.example.lenovo.eventapp.dao; 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; @Dao public interface EventDao { @Query("SELECT * FROM " + Event.TABLE_NAME ) List<Event> getEvents(); @Insert void addEvent(Event event); @Delete void deleteEvent(Event event); @Update void updateEvent(Event event); }
Create Database
5. Now, we have table defined as Entity and CRUD methods defined via EventDao.
We will have to:
- Create an abstract class EventDatabse which extends RoomDatabase.
- Add version and entities to database as @Database(entities = {Event.class}, version = 1).
- Add abstract methods of all DAO’s where the returned DAO object will be constructed by Room for database interactions.
Some things to remember:
- Version number is changed to update the database structure, when required in future updates
- The database file name must end with the .db extension
- Creating instance of database is quite costly so we will apply a Singleton Pattern to create and use already instantiated single instance for every database access.
EventDatabase.Java
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 abstract EventDao eventDao(); public static EventDatabase getEventDatabase(Context context) { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build(); } return INSTANCE; } }
Note: It is good to note that Room does not allow code execution on Main thread. Instead, allowMainThreadQueries is used to allow the execution. However, using this is not recommended on real apps. You must perform queries on AsyncTask (or handler, rxjava), otherwise your application will crash or cause ANR problems.
Implement Database Interactions
6. The below snippet will demonstrate the working of insert, update, and delete functionality using the Room database.
Add Event
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract class EventDatabase extends RoomDatabase{
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract EventDao eventDao();
public static EventDatabase getEventDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();
}
return INSTANCE;
}
}
//add event into the database
EventDatabase.getEventDatabase(getApplicationContext()).eventDao().addEvent(event);
Retrieve And Display EventList
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract class EventDatabase extends RoomDatabase{
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract EventDao eventDao();
public static EventDatabase getEventDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();
}
return INSTANCE;
}
}
//get events from database
List<Event> events = EventDatabase.getEventDatabase(getApplicationContext()).eventDao().getEvents();
adapter = new EventsAdapter(events, getApplicationContext());
recyclerView.setAdapter(adapter);
Update Event
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract class EventDatabase extends RoomDatabase{
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract EventDao eventDao();
public static EventDatabase getEventDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();
}
return INSTANCE;
}
}
//update event into the database
EventDatabase.getEventDatabase(getApplicationContext()).eventDao().updateEvent(event);
Delete Event
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract class EventDatabase extends RoomDatabase{
private static final String DB_NAME = "Event_Database.db";
private static EventDatabase INSTANCE;
public abstract EventDao eventDao();
public static EventDatabase getEventDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context, EventDatabase.class, DB_NAME).build();
}
return INSTANCE;
}
}
//delete event from database
EventDatabase.getEventDatabase(getApplicationContext()).eventDao().deleteEvent(event);
7. Open activity_main.xml and write the below code .It consist of
Recyclerview : Shows list of events.
Textview : Which shows no event found text when list contains no item.
FloatingButton : When we click on it ,It opens alertdialog to add event into the database.
activity_main.xml
<?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>
8. Open event_dialog.xml and write the below code.On update and add event I have set event_dialog.xml view to alertdialog.
event_dialog.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="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>
9. list_item_event.xml represents the single list item of recyclerview.
list_item_event.xml
<?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="20dp" /> </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="20dp" android:textStyle="bold" /> </RelativeLayout>
10. Creating adapter class for recyclerview, open EventsAdapter.Java and write the below code.
EventsAdapter.Java
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()); } @Override public int getItemCount() { return items.size(); } }
11. Open RecyclerTouchListener.Java and write the below code in which I have created custom onClickListener for recyclerview single item click.
RecyclerTouchListener.Java
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); } }
12. Open MainActivity.Java and write the below code.The below snippet will demonstrate the working of insert, update, delete and retrieve list of events functionality using the Room database in DatabaseAsync worker thread.
MainActivity.Java
package com.example.lenovo.eventapp; import android.app.AlertDialog; import android.app.DatePickerDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.AsyncTask; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.DialogFragment; 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.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; TextView noEventsFound; FloatingActionButton fab; EventsAdapter adapter; List<Event> events = new ArrayList<>(); private static TextView tv_date; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); 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)); //show list of events if exists in database new DatabaseAsync().execute(null, -1, null, null, null); //shows NO EVENTS FOUND when list is empty 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) { //show Alertdialog to edit or update the event showActionsDialog(position); } })); //add listener on FloatingActionButton to add event fab = (FloatingActionButton) findViewById(R.id.fab_add); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //adding new event showEventDialog(false, null, -1); } }); } private class DatabaseAsync extends AsyncTask<Object, Void, List<Event>> { @Override protected void onPreExecute() { super.onPreExecute(); //Perform pre-adding operation here. } @Override protected List<Event> doInBackground(Object... params) { Boolean shouldUpdate = (Boolean) params[0]; int position = (int) params[1]; String title = (String) params[2]; String detail = (String) params[3]; String date = (String) params[4]; //check whether to add add or update event if (shouldUpdate != null) { //update event if (shouldUpdate) { Event event = events.get(position); event.setTitle(title); event.setDescription(detail); event.setDate(date); //update event into the database EventDatabase.getEventDatabase(getApplicationContext()).eventDao().updateEvent(event); } else { //add event Event event = new Event(); event.setTitle(title); event.setDescription(detail); event.setDate(date); //add event into the database EventDatabase.getEventDatabase(getApplicationContext()).eventDao().addEvent(event); } } else { //delete event if (position != -1) { Event event = events.get(position); //delete event from database EventDatabase.getEventDatabase(getApplicationContext()).eventDao().deleteEvent(event); } } //get events from database List<Event> events = EventDatabase.getEventDatabase(getApplicationContext()).eventDao().getEvents(); return events; } @Override protected void onPostExecute(List<Event> items) { //get list of events from doInBackground() events = items; adapter = new EventsAdapter(events, getApplicationContext()); recyclerView.setAdapter(adapter); //shows NO EVENTS FOUND when list is empty checkListEmptyOrNot(); } } 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) { //show Alertdialog to update the event showEventDialog(true, events.get(position), position); } else { //delete event from database deleteEvent(position); } } }); builder.show(); } private void deleteEvent(int position) { new DatabaseAsync().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); //add listener to button to open datepickerdialog btn_setdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //open datepickerdialog showDateDialog(); } }); dialog_title.setText(!shouldUpdate ? "New Event" : "Edit Event"); //in case of update we want all the //fields to be set bydefault with text if (shouldUpdate && event != null) { edt_title.setText(event.getTitle()); edt_discription.setText(event.getDescription()); tv_date.setText(event.getDate()); } 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) { // Show toast message when no text is entered 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(); } //Update or add data into the database only when both field are filled(i.e title,description) if (!TextUtils.isEmpty(edt_title.getText().toString()) && !TextUtils.isEmpty(edt_discription.getText().toString())) { // check if user updating note if (shouldUpdate && event != null) { // update event new DatabaseAsync().execute(shouldUpdate, position, edt_title.getText().toString(), edt_discription.getText().toString(), tv_date.getText().toString()); } else { // create new event new DatabaseAsync().execute(shouldUpdate, -1, edt_title.getText().toString(), edt_discription.getText().toString(), tv_date.getText().toString()); } } } }); } public static class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Calendar c = Calendar.getInstance(); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_MONTH); return new DatePickerDialog(getActivity(), this, year, month, day); } public void onDateSet(DatePicker view, int year, int month, int day) { String monthVal, dayVal = "" + day; if ((month + 1) < 10) { month += 1; monthVal = "0" + month; } else { month += 1; monthVal = "" + month; } if (day < 10) { dayVal = "0" + day; } SimpleDateFormat simpledateformat = new SimpleDateFormat("EEEE"); Date date = new Date(year, month, day - 3); String dayOfWeek = simpledateformat.format(date); tv_date.setText(dayOfWeek + "\n" + dayVal + "-" + monthVal + "-" + year); } } private void showDateDialog() { DialogFragment newFragment = new DatePickerFragment(); newFragment.show(getSupportFragmentManager(), "datePicker"); } public void checkListEmptyOrNot() { if (events.isEmpty()) noEventsFound.setVisibility(View.VISIBLE); else noEventsFound.setVisibility(View.GONE); } }
Can’t seem to delete any entries.
Long press on the item you will get the edit and delete option , on tap of the delete item will be deleted from the db and list.