Top Strategies for Android App Performance Optimization

Understanding Android App Performance
Android app performance refers to the efficiency and effectiveness of an Android application in terms of its speed, responsiveness, and overall user experience. It encompasses various aspects, including memory usage, CPU usage, network requests, and app startup time. Understanding Android app performance is crucial for developers to identify areas for improvement and optimize their apps for better user satisfaction.
When users interact with an app, they expect it to be fast and responsive. Any delays, lags, or crashes can lead to frustration and potentially result in users uninstalling the app. Therefore, optimizing android app performance is not just about making the app run faster; it’s about creating a seamless user experience that keeps users engaged and satisfied.
Assessing Current Performance
Assessing the current performance of an Android app is essential to identify bottlenecks and areas for improvement. This can be done by monitoring key performance metrics such as app startup time, memory usage, CPU usage, and network requests. Developers can use tools like Android Studio, and Firebase Performance Monitoring to collect data and analyze the app’s performance.
By understanding the app’s current performance, developers can set realistic goals for improvement and prioritize optimization efforts. For instance, if the app startup time is too long, developers can focus on optimizing the app startup process. Similarly, if memory usage is high, they can look into ways to reduce it. Regularly assessing the app’s performance ensures that developers are always aware of potential issues and can address them promptly.
Be Lazy
Often when we start up some Activity, Fragment, View, Composable, we initialise all needed fields for it, sometimes it is ViewModel (which is ofc needed!) but there are also a times when we initialise things like eg Adapter for our RecyclerView or ViewPager, or other resource consuming classes. Most often then not these classes are not needed at the start of the Activity, sometimes even we do not show the Views they relate to - cuz data may be empty! In that case we are wasting precious resources which translate to our View drawing time. It is important to find these places and keep them Lazy so the resources are not used at the start of the screen, rather when needed!
Go Async
Our apps need to do a lot of work, and sometimes this work may be time consuming or even worse - it may block the main thread if you download data/call the backend endpoint on it! Then the app will look frozen for users which is already very bad! To avoid this scenario be sure that when you need to call database/call endpoint/download data or simple display image based on url - do it asynchronous! For this we are working with coroutines on a daily basis and for image we are using image loading libraries like Coil or Glide. Loading data that way will not block the main thread of the app which will speed up performance!
App Startup
When an application is started we often need to load a lot of things - be it planting a tree for a Timber, setting up your dependency injection graph with some needed right away dependencies, starting WorkManager or initialising libraries. There is also a space to improve performance here! To not waste precious resources and time to app startup use Jetpack library startup-runtime - it lets you declare things that need to be initialised and even you can specify in which order!
Flatten your View
If you are working with XML then there is a problem that happens often - nesting their Views. It is not rare to see a codebase with LinearLayout that is wrapping another LinearLayout that is wrapping another RelativeLayout etc. In that case we have some drawing issues - layouts will need to be recalculated each time a new layer of layout is added. This can create really slow View drawing. The solution to it is simple! Try to flatten your Views as much as possible or adapt to ConstraintLayout which was created with that purpose! In that case you need to set up constraints manually but that will save a lot of precious time during the app lifecycle!
State management
If you are working with Compose proper state management is a very important thing to solve performance issues. Compose is doing recomposition based on data change. If you happen to change data often and manage your state poorly then it is a recipe for disaster! But worry not, the solution as always lies in simplicity! One of the most important things is to keep your single source of truth for the state - to have one place that is managing it. Then also be sure to work with immutable data to avoid changing values from state one by one and rather update the whole model with new values. Also make sure that you are using Stable models to avoid unnecessary recompositions!
Baseline Profiles
With usage of Macrobenchmarking module it improves the first startup of an application after fresh install or update by specifying the tests and paths to specific screens by about 30% (https://developer.android.com/topic/performance/baselineprofiles/overview)! With this tool you will create additional files that will be uploaded with your APK to Google Play Store that will contain all specified paths and screens to help it load faster. Also you can prepare baseline tests for optimising usage of screens elements such as lists etc.
Small is big
Smaller the app size bigger the install numbers! It is a good and simple optimization to reduce the app size for users so it can install, update and work faster. A common way to do this is to optimize your icons, change jpg/png to SVG if possible and also run on them optimization algorithms so it is as small as possible. You should also be working with app bundles so that Google Play Store knows what is needed for which install type for user and do not install things that are not needed like language! Make sure your gradle script is optimised to not include not needed resources and code - shrinking. Also remember - DRY!
Conclusion
And the list can go on and on! Many things can be improved, in our daily job we often find some small algorithm improvement that happens to increase screen loading performance by a lot. I hope that with the things listed here you will have a basic idea on what steps you should take to improve app performance and maybe next time I will be reading your article and gaining this knowledge from you!