How and why we restructured our Android codebase for Harriken
Most people in Dhaka, at least the ones who love to eat, have heard about Harriken already. It’s a new Restaurant Discovery App for Dhaka, Bangladesh, focusing on people looking for better restaurants, maybe a better environment but on top of everything, better food.
Harriken is the new and novel attempt at making the lives of food enthusiasts in Dhaka, better than ever before. Once you discover our app, there’s no going back to the dark food ages. Finding the restaurants one loves, has been made easier than a piece of cake. Harrikenators can search for their favorite or preferred restaurant, post reviews, boast about places they’ve gone to, and even discover like-minded food enthusiasts given the social features integrated into the app.
Harriken started into market primarily with the Android app and later opened with its iOS and web platform. Harriken for Android has been on the market for less than a year now and in this short time span, we needed to upgrade and restructure our Android code base. Here’s my share of knowledge on what I learned; do’s and don’t of changing code base.
Keep in mind, this log is intended for Android Developers with around 1 year of experience. Some of this might be well known to a lot of you, but that which I had to learn the hard way.
A lesson I learned from reading different articles on Medium, a crucial one at that, is that I didn’t just drop off the entire code base and start from scratch.
Here’s what I did:
1. I started from one side, that means, starting from Splash screen, reformatted everything one by one and worked on the next one.
2. As the UI won’t be changing that much, I kept the layout files mostly untouched. So, at any time, the app was not a fresh one, rather just an evolution of the previous one.
3. This helped me to a great extent, in the sense that starting everything from scratch would take me a much longer period of time.
At first, the logic part of the code base was mostly on the Activity files. Sure, there were some helper files to access the database or shared preferences, but there were a lot of copy-pasting of functions and less re-usability. But as you’d expect, the more I treated Activity like God objects that held and controlled everything, the more I started having problems. A simple change would require me to update three to four activities, which was absurd.
This time, I started to:
1. break down the codes. The less the helper & utility files held the reference to context, the better.
2. wrap each library around in its own wrapper class, so that, at any time, I needed to change any library, all I would need to do is work on the wrapper class.
3. hold methods that needed to be accessed and used more than one time in a helper class. This increased re-usability a lot.
4. move the network calls to separate helper files and communicate via a basic interface. Previously, each network call was done in its required Activity file which made it comparatively clumsier to work with. In case if anything on the RESTful API changed, separate layer, that is, multiple separate helper classes assisted me in changing anything blazingly fast.
5. target to break down the code base in much smaller pieces so that any change or work on the code base affects smaller parts, but is conveyed throughout the whole application.
A better folder structure can help you work with much more efficiency and make the code more readable too. I always kept in mind, I won’t be the only one working on this code base, so I tried to make it as readable and efficient as possible. Better folder structure helps you navigate much faster and seek out problems easier. So rather than a flat base folder, I segmented each of the classes to where it should be, like folders for activities, fragments, models, network calls etc.
Reinventing the wheels is not a good practice for software development. Sure, we could have written basic HttpUrlConnection layer for our own purpose, but we chose to go with existing industry-proven libraries for Http calls. We tried to use libraries for major functionalities like image loading, Facebook login, network calls, crash reporting etc. Primarily, this also resulted in using a lot of pointless libraries that I could have easily avoided by adding a simple method or class. Soon I hit the holy 65K methods limit; had to use Multidex. After reformatting the code several times, I have lessened the number of libraries to a bare minimum and the method count came down to around 53K, which was indeed a great advancement.
“Out of Memory errors” are the ones we frequently faced back in the day. We had a very basic and simple design pattern, depending mostly on Singleton classes for data communication between activities. Singleton objects, regardless of how awesome and handy they might be, pose a greater threat. Every singleton object is a static object that occupies RAM. Extensive use of Singleton class, along with lots of variables as static variable, made the app crash frequently after visiting a few pages.
LeakCanary is a great library that helped me mark the issues. What I did then to minimize out-of-memory errors is that:
- added clear reference to each class variable used.
- added destructor methods to each class and called the destructor at onDestroy() method of each Activity.
- tried to minimize holding Context reference as less as possible.
- minimize use of static variables as low as possible.
Harriken, in it’s first release, had an APK size of around 5.4MB, which gradualy increased to about 7MB. Now, 7MB is not so big for an android app, but I started to look for ways of minimizing the APK size. What I did for that is:
- analyzed the APK file with the built-in tool for APK analyzer in Android Studio.
- removed all unused resource files
- distributed few common resources to respective drawable with the corresponding size
- heavily reduced static image size using ‘pngquant’
- resized custom fonts .ttf file to reduce its size using ‘Glyphs’
- wherever I could, converted few image resource to vector drawable
- correctly set up Proguard properties
Finally, after factoring lots of images and assets, I brought down the APK size to around 3.4MB, which is a huge improvement from the first one released.
Initially, Harriken code-base used SVN as version management system. After much thought, I shifted the code-base to Git and added a Wiki for the project. Anyone who does not know how and why things work in code can look up the project Wiki and get started very soon. I also added a README to hold the libraries, custom keys, app level configs log, and a code-base formatting guideline. Whenever I get confused about any code formatting or writing structure, I take help from the README file.
The Harriken Android code, at present, has a generic pattern and a basic structure. What helped me go through all the changes, and iterate through functional changes is different articles from Medium and other online media. Each article guided me to something better and more useful. The Android Studio keyboard shortcuts have accelerated the process of refactoring and changing a great deal. Without these guidelines and tools, I’d still be struggling with basic logic building and debugging.
CONCLUSION
When we started with the requirement for the Android app on October 2015, things used to be slightly different. My then-colleague and I were just fresh out of university, we never had any serious project to work on prior to this. I can vouch for myself, being a fresh EEE graduate, with Android Development experience of barely one or two ‘Hello World’ projects. We had this somewhat big project handed over to us, which had to be completed within two months. Although we couldn’t finish it within two months, it took us about five, but we did manage to finish and release it by March of 2016. The code-base was just how you’d expect two freshers to make — a bit clumsy, very little code formatting, and direct codes hard-written without any modularity. But it worked! Sure, it crashed every now and then, but we had it under control. At least people were using it.
As necessity arose, it was around September that we felt the need to upgrade our database and API code base. Taking the opportunity of being the sole person working on the Android code base, I started working on changing and upgrading the database. And here I am, with not the perfect, but the much more workable and readable Harriken for Android v2.0.
This ends the blog on how and why we restructured our android codebase for Harriken. Feel free to comment, like, recommend, share!
Riddhiman Adib is currently working at Harriken.com Limited as the Android Lead. Find out more about him at: riddhimanadib.me and follow his blog at My Online Cafe to get updates on Tech Stuff!