Creating a ToDoList Android Application with Android Architecture Components - PART 2

Words
1022
Reading
5 min
Listen
Play
8y

Repository

 https://github.com/googlesamples/android-architecture-components/ 

What Will I Learn?  

  • How to create a ToDo Listing Application 
  • Implement  Database operations on a separate thread Using Executors.
  • Implement  Swipe to delete functionality in the RecyclerView

Requirements  

  • Java knowledge
  • IDE for developing android applications(Android Studio or IntelliJ)
  • An Android Emulator or device for testing
  • Must have read the Part 1 of this series

Other Resource Materials  

  1. Executor Framework
  2. https://developer.android.com/reference/java/util/concurrent/Executor
  3. The Singleton Pattern
  4. RecyclerView Swipe

Difficulty  

  • Intermediate

Tutorial Duration 20- 25 Minutes 

TUTORIAL CONTENTS

In the Part 1 of this tutorial series, we started off by creating a database with the Room library where To_do task are added based on their priority. In this Part Two of this series, we are going to implement the Room database operations on a separate thread using Executors and also include the swipe to delete feature on our Recyclerview. Lets get started...

Step 1 : Disable database operation on the main thread

In the AppDataBase class, where the singleton class is initialized,remove the . allowMainThreadQueries() . Runing the app now should crash, telling you database operations can not be accessed on the main thread. Let's proceed to fixing this error.

remove the rectangled line of code

This is the error 

Step 2 : Create a new Singleton Executor Class and name it AppExecutor.

What is an Executor?

According to the class documentation, an Executor is an object that executes a submitted runnable tasks. It is normally used instead of explicitly creating threads for each of a set of tasks.

Using a singleton class ensures that we have only one instance of our executor object which is just beautiful, when you consider memory resources  on android. This makes us a good citizen of android....

Here is the code of the Executor

public class AppExecutor {
   //this is for singleton instantiation
   private static final Object LOCK = new Object();    private static AppExecutor sInstance;    private final Executor diskIO;    private AppExecutor(Executor diskIO) {
       this.diskIO = diskIO;
   }    public static AppExecutor getInstance(){
       if (sInstance == null) {
           synchronized (LOCK){
               sInstance = new AppExecutor(Executors.newSingleThreadExecutor());           }
       }
       return sInstance;
   }
   public Executor diskIO() {
       return diskIO;
   }
}

Code Explanation

As you can see from the code block above, we create a singleton class so as to have a single instance of the class. This class has a private constructor which will be initialized in the getInstance method. The Constructor has one Executor parameter called diskIO. The disk IO is a single thread executor. Only when the diskIO object is null will the AppExecutor object get created with the new key word.

Step 3 : Implement the Executor in the EditorActivity

I the editor activity where we have the button to add a new task, we replace with the following block of code

buttonAdd.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
       // get text from user
       String text =  etTask.getText().toString().trim();
      int priority = getPriorityFromViews();
      Date date = new Date();
       //create new task object
      final Task task  = new Task(text,priority,date);
      AppExecutor.getInstance().diskIO().execute(new Runnable() {
          @Override
          public void run() {               mdb.taskDao().insertTask(task);               finish();           }
      });
   }

});

Code Explanation

  • The onclickListener is where we add a new Task to the database. Firstly we create a new task object passing the user data as its parameters that is the text, priority and date. 
  • Now we implement the AppExecutor class with a new Runnable object.
  • In the run method of Runnable object, we include our database code

Step 4 : Implement the Executor in the MainActivity

After adding a task, we need to see the UI refresh immediately so we do some database operations in the onResume method with our Executor class.

Also we need to add swipe to delete functionality to our RecyclerView and refresh the UI. This will require we do a database operation within the Runnable object executed by our AppExecutor class.

Since we have to call the AppExecutor.getIstance twice, we will create a method were all the code will go, so as to prevent writing long codes in two places.

Create a method and call it getTask

private void getTasks() {
   AppExecutor.getInstance().diskIO().execute(new Runnable() {        @Override
       public void run() {
           final List<Task> tasks = appDataBase.taskDao().loadAllTask();      
         runOnUiThread(new Runnable() {    
            @Override                public void run() {
                   toDoListAdapter.setTasks(tasks);                }            });
       }
   });
}

Code Explanation

What the above block does basically is to get the list of task from the database which is then set to the adapter to display on the UI. Here we use the runOnUiThread to get acess to the UI thread in order to  refresh the RecylerView.

Implement the Swipe to delete feature in the MainActivity

We want to make our recyclerView respond to both left and right swipe whereby we could then write our database code to delete that specific item from the database.To allow swipe, we use the ItemTouchHelper class of the android framework

here is the code

new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
    @Override
   public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
     return false; // We return false because we are not going to use it
   }
   // Called when a user swipes left or right on a ViewHolder
   @Override    public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
       //  implement swipe to delete
       //get item position        final int position = viewHolder.getAdapterPosition();
       
       // get list of Task
       final List<Task> tasks = toDoListAdapter.getTasks();
       AppExecutor.getInstance().diskIO().execute(new Runnable() {
           @Override            public void run() {
               appDataBase.taskDao().deleteTask(tasks.get(position));
           }
       });
       getTasks();
   }
}).attachToRecyclerView(recyclerView);

Code Explanation

  • Basically we allow the swipe on both directions of the recyclerView with the constants ItemTouchHelper.LEFT and ItemTouchHelper.RIGHT
  • We get the task position in the adapter using viewHolder.getAdapterPosition();
  • We get the List of task from the database
  • We call the deleteTask method of our TaskDataAccessObject interface.
  • getTask method is called to refresh our UI.

Step 5 : Test the App

After refactoring our codes to implement our database operations from a separate thread using Executors, and also adding the swipe to delete feature to our recyclerView, we can now proceeding to testing the app. Below is the app demo.

Curriculum

Creating a ToDoList  Android Application with Android Achitecture Components - PART 1

Proof of Work Done

The complete source code can be found on github

https://github.com/enyason/TodoApp_Android_Architecture_Components