In my previous post, I already explained the concepts that I used to implement the simple to-do list app. But unfortunately, it wasn’t enough. There were several difficulties that I faced because of my lack of knowledge in coding Android and Android design pattern. Luckily, I was able to dive in more to know about Kotlin in Android and Android Architecture/Design Pattern.
Before we continue in discussing my way of tackling the difficulties, here is a glance of my final simple to-do list app.
Task Deletion: Don’t Pass the Index! Pass the Element
When I first implemented deletion of the task, I only thought that the task need to be immediately disappeared from the recycler view. Because of that, I only passed the position of the task element using callback in the view holder to the recycler view adapter.
Little did I know that passing the position instead of the task element itself would cause a wrong task deletion when the to-do list app was in search mode. When we are querying the tasks from the to-do list app, the recycler view will only show the result of querying tasks. And by that, when we delete a search result task, we will get wrong position of the task in the shared preference.
For instance, when we are searching for a task and the result is a task that is shown on top of the search result, the view holder will pass the position equals to 0 to recycler view adapter. This case will be safe if the search result task actually appears on position 0 (on the top) of the recycler view when the app is not in search mode. However, if it is not, the task on position 0 of the recycler view when the app is not in search mode will be deleted (which is not the task that we expect to delete).
To overcome this issue, I finally passed the task element to do the deletion. Within the class that handle the shared preference, the task removal is done if the expected task to be deleted is found. And by that, I don’t need to be worry about any wrong task deletion anymore :)
Better Understanding in Clean Architecture for Android
This is a really sincere tip from me for whoever is a beginner in learning any language or platform-based development : read about the architecture that you are going to utilise in your code implementation first.
It was really painful to understand the mess (read: code) that I created using MVP design pattern, but yet I implemented the MVP wrongly. It turned out that I hadn’t moved on yet from iOS, so I tried to implement MVP of iOS development in Android… which was a really b̵r̵i̵l̵l̵i̵a̵n̵t̵ bad idea.
At the end of the day, thankfully, I found a tutorial to implement MVVM with Clean Architecture in Android in here. But since I wasn’t really familiar with MVVM and I didn’t have enough time to really dive in into MVVM, I decided to implement MVP and Clean Architecture in the to-do list app.
In Clean Architecture, the most inner circle is the most abstract and the most outer circle is the most concrete meaning that the inner circle is the business logic of the application and the outer circle is the implementation details (also called Abstraction Principle). Other than that, Clean Architecture also applies Dependency Rule where each circle is only allowed to depend on its nearest inner circle.
The graph above is the clean architecture that I tried to apply in the to-do list app.
- Presentation : In this layer, the view to able user interaction exists.
- Use cases : All the available actions that can be triggered by user is defined here.
- Domain : App’s business logic.
- Data : Data source definition.
- Framework : Concrete implementation for the data layer.
With that architecture in mind, I finally implemented a presenter that can react to the user interaction from the view and pass action to the data source.
Using Extras to Pass Data between Activities
As promised from the previous post, I would discuss about how I created the functionality of Add task. But I won’t really go into details or any code snippet, once again, I will just reveal what Android concept’s that I use to implement it.
At first, I was directly accessing shared preference from the Add task activity to save the task inputs. It was good for me until I finally had to implement the Edit task functionality. Bam! I finally thought it wouldn’t be suffice to kept using shared preference whenever I wanted to pass data between activities.
There were three main reasons of why I finally decided to use extras instead of shared preference in passing data between activities. First, the passed data wasn’t really complex and large. Second, the view that would be updated by the data change is always the Main (to-do list) activity. And last, my implementation was violating the SRP principle where it didn’t utilised any new presenter for each Add task and Edit task activity and implemented the saving and updating shared preference directly in the activity instead.
I know I was really bad in implementing the architecture back then :)
By those three main points — thank God I finally became way smarter — I decided to use bundle extras. With that, the parent activity can be notified by its children activity whenever there is a data change from its children. In the parent activity we can ask for the updated data from the children activity by launching it with
startActivityForResult and override the
onActivityResult to handle the data received from the children activity. Meanwhile, in the children activity, we only need to pass the result code and the intent containing the bundle with
Pretty simple, isn’t it?
In conclusion, facing the difficulties or even bugs when I built the to-do list app had led me to delve in more about Kotlin and Android. I was finally could understand the architecture, design pattern, and concepts way better because of that difficulties.
Now I really can relate and value more on the saying,
The pain you feel today, will be the strength you feel tomorrow.
Please keep on learning new things, mate! :D