Composition Over Inheritance

One of the constant debates in Android-dom is whether “global data” should be maintained in a singleton or in a custom Application object. Apparently, the Application is kept around until the process hosting that Application is killed or recycled, meaning that its lifetime is equivalent to a static data member, such as a classic singleton. That means that the primary benefit to a custom Application is that Application is a Context, meaning you have access to a lot of utility methods (e.g., resource getters) that some arbitrary other singleton would lack.

If you are creating Android library projects or other forms of reusable code, you may want to have some global data that, in the absence of other considerations, would be a good use for a custom Application object. Hence, you might create a library that mandates that those using your library must use (or extend) your custom Application object, adding the android:name attribute to the <application> element in the manifest to have Android use that custom Application subclass.

However, if every library does this, then developers are screwed.

Java does not support multiple inheritance. If Library A says “you must use my custom Application class” and Library B says “you must use my custom Application class”, then a developer cannot use both Library A and Library B.

This is bad, and is a fine example of where inheritance makes things more brittle than they would otherwise need to be.

A better approach — besides perhaps just using an ordinary singleton — would be to use composition:

  1. Create a class (e.g., com.library.a.ApplicationFacet) with a constructor that takes an Application as a parameter, so instances of that class have access to the application-level Context
  2. Define an interface (e.g., com.library.a.ApplicationMixin) with a getter for an instance of your class from step #1 (e.g., a gimmeMyFacet() returning an ApplicationFacet)
  3. Mandate that developers implement your interface on their custom Application class

This works even with multiple libraries, since a class can implement multiple interfaces. So long as each library is using its own Java package, there will be no collision on the methods or objects.


Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!