During the development of an Android application for a clinical diagnosis platform, an issue with Android Lollipop came up, we had not had that problem on other versions. The app was based and focused on aesthetic resources, with many images in each activity (background, imagebuttons shines, shadows) and assorted animations in transitions and interaction with the user. Its apk currently takes up 1.5 GB, specially, because of the size of the videos it contains, it is a heavy app that makes user experience, regarding the flow of the application itself, largely dependent on the device running it.
In this environment, we first developed the application for 10 “tablets, then for 7″ and finally for 9”. In the process, we used the emulator Genymotion to test the development on Android versions 4.1 and 4.2, to a greater extent. When starting to adapt to 9 ” with a virtual device Genymotion Twidroyd 9″ – 5.0.0 (Lollipop), we were surprised that the app, after the transition of a few screens, suddenly stopped and the Android Studio debugger reported shortage of memory (OutOfMemory). That had not happened before with the same app version! This is why we recommend testing applications on various emulators for different Android versions, because there may be a difference in the behavior of the components from one version to another.
Fully aware of the weight of the application, we wondered why this had not happened before, when we tested on 10 “and 7”. It was then, after thinking for a while and ruling out other problems that we suspected of the Android version. That’s when we monitored memory usage during the application execution and noticed that the memory allocation increased from the early start. It had smaller low’s but in general, but the trend was to increase, especially in the transition between activities.
By doing some research on the web, we learnt that the Android 5.0 Lollipop version had had several memory leaks since its release. Among them, a very serious one, was one in which the automatic cleaning of RAM and disabling processes stopped in order to make use of the space, which resulted in applications being stopped or crashing automatically, making the devices virtually useless.
While many issues related to the use of memory were fixed in version 5.1 there are still several to be solved. In our case, we tried on Lollipop 5.1 and very little changed: we still suffered from Out Of Memory problems, even when testing with the different emulators.
Anyway, we persisted and continued investigating the possible causes of this memory failure. Finally, we came up with the solution to free the resources used in activities by hand, whenever these are stopped or sent to the background:
When we entered these activities with Pagers two or three times in-a-row, the memory increased sharply. There were two important resources that were not being freed in the code copied above, so we decided to make the FlipViewController and PageAdapter attributes static.
Now, we were “recycling” these components that were apparently costly, so that there is only one instance of them at a time. Thus, we eliminate crashes and stabilize the memory usage while the app is running, making it remain below 100MB on most screens, going over it by a few MB in some sectors.
Another point we should specially emphasize is the treatment of bitmaps, since such objects are the most memory consuming. The misuse of these can make us quickly occupy the allocated memory by the operating system and suffer from the sudden crash of our application.
As for the bitmaps, we want to leave some tips to consider:
- Saving images with the size in which we will eventually use them and not in the original size. The size of images in memory occupies three to five times more space than the actual size.
- Compressing images is not the same as saving them with the size to be used.
- Caching images.
- Do not adapt the image to the assigned layout container at the time of rendering screens is an important factor for the app to run at its optimal speed, which translates into a better user experience.
- Do not have global resources which are not freed when running the app.
It was not simple at all and we had to walk a long path of trial and error to overcome the problem of memory leaks in this app. The idea of reflecting that path on this article is to make the experience helpful to those reading and prove that perseverance is a key ingredient when developing. Happy coding!