Effective Java for Android

Selim Salman
3 min readApr 6, 2017

--

So let us start by declaring some differences between Java vs Android:

  • Android Apps are written in Java but the end result does not run on a JVM but run within DalvikVM or ART.
  • Not all JSE APIs are available within Android Platform.
  • Threading is kind of different (Main thread vs Background threads and tools/APIs associated with them)
  • No Main function but a special Activity lifecycle (even somehow behaviour changed within API > 24 Multi-window mode)
  • UI is defined on XML
  • There are preferred ways or APIs to be used within Android rather than the Java standard APIs.

Why we will try to delve into Best Practice Java APIs for Android? because the 1st class citizen: the Battery. Even current devices are equipped with great capacity of processing power, memory and storage, we are still having a big problem with Battery drain. So any little optimisation would save energy and make users happier!

So besides many advices on Effective Java book (by Joshua Bloch) which can be applied in the Android world but with care, I like to highlight the following:

  • Keep it Simple and Smart (Readable) so use Abstraction when really needed but do not overuse it.
  • Check previous code and try to find reusable patterns and components.
  • Use <final> whenever possible.
  • Use static internal classes to avoid memory leaks.
  • Use StringBuilder instead of ‘+’ operator.
  • Initialize containers with expected capacity whenever possible.
  • Use enhanced loop syntax when possible:

for(int x : integers){//…}

  • Do not allocate memory if you can ignore it. Fewer objects created, less garbage collection, better user experience.
  • Allocate memory if your method is going to be called many times and it gives the same result:

int len = localArray.length;

for (int i = 0; i < len; ++i) {//…}

  • Use optimized containers when possible (instead of HashMap, use ArrayMap or SparseArray; ArraySet instead of HashSet based in use case). Check android.util and for compatibility android.support.v4.util packages.
  • Use android.support.annotation whenever possible (e.g. Nullability checking @Nullable)
  • Avoid enums when there is no critical need, and use this:

// Define the list of accepted constants and declare the NavigationMode annotation

@Retention(RetentionPolicy.SOURCE)

@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})

public @interface NavigationMode {}

// Declare the constants

public static final int NAVIGATION_MODE_STANDARD = 0;

public static final int NAVIGATION_MODE_LIST = 1;

public static final int NAVIGATION_MODE_TABS = 2;

// Decorate the target methods with the annotation

confluence export

@NavigationMode

public abstract int getNavigationMode();

// Attach the annotation

public abstract void setNavigationMode(@NavigationMode int mode);

  • Cascade calling constructors for custom views but be aware of overriding Super parameters. Cascading methods is the standard Java idiom for defaulting the values of some arguments. All the code that actually

*Disclaimer: “Effective” expression by itself is debatable. I tried to put some of the best practices (in Java language perspective) to implement. From the code I have seen in different projects and as suggested by Google Android Community, this document is started and should be considered as an initiative point where it can be modified and adding more best practices to have more consistent way in coding projects. (In this article I will consider just Java perspective; there are still many best practices within Android itself for profiling and performance)

--

--

Selim Salman

Diversified Software Technologies Engineer/Evangelist, Ubiquitous Computing Researcher, Digital Nomad!