Good Practices to Become a Great Android Developer — Part 2

Julián Falcionelli
Major League

--

Here’s some advice on optimizing your work as an Android developer.

1. Improve the performance of Android Studio

Many times if we are working with various projects and virtual machines our computers start to get slow.

By default, when you install Android Studio you are assigned a maximum memory for our Virtual Machine, which can be increased to give more space and lighten our computers.

To do this we must edit the file studio.vmoptions which can be accessed from Help> Edit Custom VM Options.

There increase the Xmx value which represents the maximum memory allowed to the JVM.

My VM Configuration

Do not forget to restart Android Studio to apply the changes.

2. Gradle Config Fields

Many times we have variables that have certain values according to different execution environments, for example, we can have an API that has several environments, like staging and production, and to switch between them we have to change the URL to the desired build.

One way to automate this process is by using buildConfigField from the Gradle of our module.

For example:

From java:

3. Signing information

Often to use an API is necessary to register our application using the SHA1 key certificate of your Keystore.

To get it easily just run the signingReport task from Android Studio.

Then Android Studio will list the information for each Build Variant.

4. Lightweight APK

Sometimes we forget to remove unused resources (assets, xmls) and this causes an increase in the size of the apk.

To avoid that use the shrinkResources property in the Gradle of our module which removes unused resources.

5. Crash Reports

Before making an application public I recommend to integrate crash reporting, as Firebase Crash Reporting, that will be very useful to monitor how is the app running and can help us to quickly solve issues.

Crash reports console of Firebase

To prevent the report of crashes when we are developing you should activate it only for release builds.

From Gradle 2.2+ you can add dependencies agreement specific flavors/buildtypes.

For example, we can enable crash reporting only for release builds:

6. Full lifecycle test

To avoid problems in the future you have to make sure that you test all the features of your app in the entire lifecycle of our activities/fragments.

Often, we don't know how to test the behavior of our app after it is destroyed, especially when it only supports one orientation.

An easy way to force the execution of the onSaveInstanceState method is activating the option “Don't keep activities” in our Developer settings of the device.

To save/restore data i recommend to use the Icepick library, it will save us a lot of code.

A bit of Icepick

7. Best alternatives to findByViewId

At this point I do not think there are developers using the findByViewId expression to bind views, most must have replaced that tedious way with Butterknife, a library that allows us to bind views and events through annotations.

A bit of Butterknife

Another alternative is to use Data binding, which gives us a bidirectional connection between a view and a variable so that when you change one of the two, the other also does it (through observable pattern).

Depending on how much you use this alternative, it can cause you to have your layouts more coupled to the activities/fragments which is not good.

A bit of DataBinding

8. Global Styles to save code

Using styles appropriately can make our layouts code much simpler and neat.

One way to avoid repeat attributes is defining in the theme of our application defaults values, such as:

In your manifest:

Thus all views will have by default wrap_content as width and height .

9. Serializable vs Parcelable

To pass information in our intents we need to implement Serializable or Parcelable in our classes.

Many times we choose Serializable for its simplicity, but if the flow of our application is very large it is recommended to use Parcelable, which is considerably more optimal in relation to the performance of Serializable. This is because Serializable works using Reflection which means that the variable types are defined at runtime. This consumes more processing, which doesn’t happen using Parcelable because you explicitly must take care of the variables serialization.

Luckily there are many generators that help us with the implementation of Serializable in our classes like http://www.parcelabler.com/.

Wouldn’t it be great if Android Studio could generate parcelable code like it does with getters and setters?

10. Uncoupled code = Maintainable code

I use Dagger2 for dependency injection and Inversion of Control to keep the code as uncoupled as possible. If you are not familiar with the term dependency injection and inversion of control I recommend you go through a post I wrote a while ago where I explain the SOLID principles.

Another pattern that we used to abstract the data source of our activities/fragments is the Pattern Repository.

Repository Pattern (by Fernando Cejas)

To have a more uncoupled code I recommend using MVP instead of the default "MVC".

Here’s a Base Project that uses Dagger2 + IoC + Data Binding + Repository Pattern and many useful classes as SharedPreferences handling, sessions, utils, etc.

I recommend you to read about Clean Architecture.

--

--