I never had to deal with any memory management before (and technically, I still didn’t have to) so I started crawling through StackOverflow(SO) for a solution. At some point, I got my memory footprint down by calling the recycle function on the Bitmaps I wasn’t going to use, and by calling the System.GC function whenever I knew a garbage collection would free up some allocations. This resulted in the memory graph as shown above.

In my quest through the Android section of SO, I had seen the name Picasso dropped a lot. This is an image library that took care of the same problem I tried to fix and did more. After a while of struggling with doing my own memory management, I decided to jump the gun and import the dependency. I was amazed: not only did this manage my memory way better than I did by doing things like caching images that might be needed later instead of reloading them every time, it allowed me to remove all my networking code regarding images.

Sayonara, ImageRequest.

By using the Picasso library, I was able to remove the class shown above and all the code that took care of processing that image (resizing, scaling correctly, making it circular) and replace it with this single line of code:

This was my eye-opener. If I could make my life that much easier with this one library, how many other brilliant libraries were still out there, waiting for me to integrate them into my code? That same day I replaced all my networking code with the OkHttp library, further improving my memory footprint by not having countless strings allocated by a StringBuilder parsing a JSON file.

API Levels

This has been a hurdle, to say the least. It’s definitely just something you need to get used to, but it’s a hassle at first. We all know that great feeling of finding a solution to the exact problem you’re having on SO. Android developers know how that feeling can get crushed by looking up the specified methods in the documentation and finding out the required API level is higher than the lowest one they have to support. What follows is a scavenger hunt to find out the inner workings of the method, and to try to replicate its behaviour. An example of this is when I wanted to execute something after an AnimatorSet finished animating:

An extension function for the AnimatorSet class.

With API level 24 and up, we can use the getTotalDuration method and use its result in a postDelayed block. Sadly, my app had to support lower API levels so I wrote the above implementation.

Nice bonus: the extension function, as shown above, can also be called at points between animations while creating the AnimatorSet object, to fire code blocks at certain points during the animation! :-)

This taught me a valuable lesson: take some more time looking through SO. Answers from 2013 might not be relevant at all anymore, and new answer are often a lot further down the page! An example I’ve used earlier is JSON parsing. This was one of the first things I built into the app, as it had to communicate with the backend I made for it. The first Google results wrote about using BufferedReaders and StringBuilders; a lot of boilerplate that does something very simple, allocates a lot of Strings and clogs up memory debugger with them. If I had taken some more time to scroll down the page of SO I would’ve found the great suggestions on using the GSON library or the OkHttp library for network requests.

Wrap-up

I could try to write a section about the interface builder, but the truth is I suspect I just don’t grasp that fully yet. I’ve embraced Xcode’s interface builder, and Android Studio just uses a lot of different terms and principles.

The most valuable lesson I’ve learned is to keep an open mind at all times. It’s easy to turn on tunnel vision and to try and find a solution similar to what works on iOS, but often it just isn’t that simple. You shouldn’t think about refactoring what works on iOS to Android, you should try to find a solution that works for Android. Whether that is using a library or writing your own solution to a problem, you shouldn’t be afraid to try new things.