In my few years of experience developing Android applications I have come to appreciate that certain practices if followed consistently make the work easier, faster and all the more enjoyable. In the pursuit of consistent productivity I have curated a recipe that enables me to produce work that I can be proud of.
1. Follow an Architecture
Consider this scenario: you use the android framework as it comes out of the box, no bells or whistles. You want to retrieve a list of items from your backend and display them in activity A. All this logic is handled in activity A and works seamlessly. Later a new feature requires you to retrieve the same items, process and combine them with another list of people also retrieved from the backend before displaying them in activity C. You could:
Rewrite the API call from activity A in activity C and add the additional logic to process and combine them with the list of people or extract the API calls to their own class, essentially creating a data layer. You would then access your data layer via static references from the activity or use an event bus to post and subscribe to the data returned from the servers or alternatively;
Organize your project into distinct modules, each responsible for only one thing. For example your activities would only be responsible for rendering views. A separate module would be responsible for data access only while another would only be responsible for the implementation of your business rules.
Option B would give you greater flexibility by removing the tight coupling between the Android framework and your logic. This makes maintenance easy and improves the testability of your application. It would solve the problem with option A by defining a single source of each piece of data that you can reuse in multiple parts of your app quite easily via dependency injection. You can achieve this by following popular design patterns and architectures like MVVM and MVP. There are numerous tutorials and opinion pieces that vary widely on how these should be implemented but a good starting point for MVVM would be this. I also have a template for MVP apps that you can use once you get the hang of it. As for which is better between MVP and MVVM all I can say is that the jury is still out.
2. Track App Crashes
On your development and test devices your app will almost always work seamlessly right up until it is deployed to production then the sky comes tumbling down. You most probably have two separate backend instances for debug and release that ordinarily would vary. Besides this, you will also most likely be deploying your app to multiple devices with varying android versions from different manufacturers. As such it is difficult to cover all possible cases in your implementation and testing. For the crashes you don’t catch before deploying it would be nice to know which exact part of your code broke and on which devices or android versions the problems arose. I use Crashlytics to get detailed stacktraces. Debugging crashes from here becomes a breeze.
3. Make your code pretty
In addition to structuring projects properly, the visual appearance of code helps with readability. To make your code pleasant to look at and hence easier to understand there are a few suggestions to consider:
Format all the files in your project using a style guide for example Square’s java code style that organizes, indents your files consistently and even removes unused imports.
Adopt and enforce a consistent naming scheme throughout your project. This is particularly important for a team since everyone would have their own preferred style but a mutually agreed upon style would reduce the cognitive load in reading every other team member’s contributions. This extends even to the choice between camel vs. snake case.
Name your widgets in the layouts distinctively. For instance I would name textViews that I use to display the app name inside my Splash Activity and another in the Home Activity thusly: @+id/splashActivityTvAppName and @+id/homeActivityTvAppName respectively. This distinction helps to avoid a mix up in case you want to refactor one widget and rename it while retaining the other as is which would not happen had both of them been given the id @+id/tvAppName
Extract all the strings to either strings.xml or a constants class. Literal strings in your code are ugly. That’s all. Hardcoded strings in your layouts will have you repeating yourself in cases where you could reference a string from your string resources and reuse it anywhere else. Should you need translations for your app, you will have to extract all the hardcoded strings from your layouts so why not have extract them from the get go and save yourself a few days of mind-numbing, repetitive labour?
Use data binding instead of casting individual views. You will write less code this way.
Package your classes by feature. This groups all relevant code for a feature and makes tracing implementation details easier.
4.Use an ORM for local persistence
More often than not you will want to deliver an application that works regardless of the network connectivity status. The android framework provides a SQLite database to help with storing structured data in the device to this end. Using an ORM would abstract a lot of the raw SQL you would otherwise write, making local database operations a breeze. There are several ORMs available to you depending on your preferences and needs. A safe choice in my opinion would be Room from google since it is actively maintained and it is quite robust; it includes support for relations, type converters, tests and migrations.
These are a few of the practices whose persistent application I find adds consistency and predictability between multiple projects ,allowing effort to be focused on solving the problem instead of grappling with the framework.
iHub Software Consulting is a design-led consulting firm that offers best-in-class software development and design consultancy. Our services include user experience research, design thinking facilitation and software development. Interested in learning more about our work? Talk to us on [email protected]