Dependency injection android

The moment I decided to become Android developer I bought a book about professional software development. Luckily, an entire chapter in that book was devoted to the concept of dependency injection.

To tell you the truth, back then I did not immediately understand what dependency injection is. I also couldn’t appreciate the prominence of dependency injection in object oriented design. However, the sole fact that I read about it gave me a good head start. Later, when I came around dependency injection in context of Android, I knew that it is important to learn how to use it.

Since then I experimented with various approaches to dependency injection implementation in Android. It is through these experiments that I developed a very deep understanding of its concepts and practices.

In this post I will share with you what I learned about dependency injection in general and also share several best practices for dependency injection in Android.

First things first:

Let’s first clarify the terminology that I will use throughout this article.

When code in class A references class B we say that class A depends on class B. In this context we can also say that class A is a “client” of class B, and class B is a “service” for class A.

Client Service

Please note that if code in class B also references class C, then class B is a client of class C, and class C is a service for class B.

Therefore, the same class can be a client and a service at the same time when looked from different perspectives.

Dependency injection:

Dependency injection is an overloaded term.

The basic usage of “dependency injection” (all in lower case) refers to the action of providing (injecting) services into clients from “outside” (as opposed to e.g. instantiation of services inside clients).

Dependency Injection (note the capitalization), on the other hand, is the name of an architectural pattern that defines the techniques, the principles and the associated best practices that “extrapolate” the fundamental techniques of dependency injection to a system level.

Note that the two interpretations above imply completely different levels of abstraction: dependency injection “lives” at class level, whereas Dependency Injection “lives” at system level.

The multiplicity of interpretations of “dependency injection” causes quite a bit of confusion in development community.

In my experience, most developers aren’t aware of the ambiguity of the term, which leads to endless debates over what dependency injection is and what it isn’t. This doesn’t happen when the level of abstraction is explicitly stated, in which case the discussions tend to turn away from terms’ semantics and become more technically oriented.

Dependency injection fundamental techniques:

As I said, the first interpretation of dependency injection is the action of injecting services into clients from “outside”.

In Java, there are just three fundamental techniques for performing dependency injection: Constructor Injection, Method Injection and Field Injection.

One interesting fact to note with respect to fundamental dependency injection techniques is that we all use them from day one of our experience with object-oriented languages. Therefore, the question “do you use dependency injection” may be automatically translated into “do you use Dependency Injection architectural pattern” because otherwise it simply makes no sense.

Dependency Injection architectural pattern:

Dependency Injection architectural pattern “extrapolate” the fundamental techniques of dependency injection kisted in the previous section to a system level.

The main characteristic of correct implementation of Dependency Injection architectural pattern is segregation of application’s logic into two disjoint (in mathematical sense) sets of classes:

  • Functional set. Classes in this set encapsulate core application’s functionality
  • Construction set. Classes in this set resolve dependencies and construct objects from the Functional set

Construction and Functional Sets

In order for the above sets of classes to be disjoint, the following conditions must be satisfied:

  1. Classes that encapsulate core application’s functionality mustn’t resolve dependencies or instantiate classes from Functional set
  2. Classes that resolve dependencies or instantiate classes from Functional set mustn’t encapsulate any of core application’s functionality

Segregation of logic into Functional and Construction sets of classes is manifestation of Separation of Concerns principle. In other words, Dependency Injection separates two system level concerns: core application’s functionality and application’s construction logic.

Functional and Construction sets integration:

Though disjoint, Construction and Functional sets must be integrated together. At the end of a day, they complement each other and constitute a single application.

Construction and Functional Sets Integration

There are two main approaches to this integration:

  • Pure Dependency Injection (aka. Poor Man’s Dependency Injection)
  • Dependency injection frameworks

Let’s review each of them individually.

Pure Dependency Injection:

Pure Dependency Injection, also known as Poor Man’s Dependency Injection, is a manual approach to integration of Construction and Functional sets. When using Pure Dependency Injection, you are in charge of designing and implementing all the integration logic.

Pure Dependency Injection

The change of name from Poor Man’s Dependency Injection to Pure Dependency Injection was proposed by Mark Seemann in his blog post about Pure DI. Pure Dependency Injection is a much better term that does not introduce prejudices into developers’ minds (as it happened to me).

The advantage of Pure Dependency Injection approach is that you have complete control and do not depend on any third party code. It might also be the least complex approach because the flow of control is straightforward and is easy to follow, and there is no “magic” involved.

The downside of Pure Dependency Injection is that it is very easy to get wrong.

If the team that chooses Pure Dependency Injection is not skilled or not disciplined, Pure Dependency Injection approach might lead to maintainability overhead. Additional downside is that all the logic, including a considerable amount of boilerplate, should be written from scratch.

In practice, I think that in most cases you’ll be much better off using a mature dependency injection framework.

Dependency Injection frameworks:

Dependency injection frameworks are libraries that assist in implementation of Dependency Injection.

Note the “assist” part – Dependency Injection can be implemented without any frameworks at all in the form of Pure Dependency Injections, but usage of a mature framework can spare you a lot of work and headache.

Dependency injection frameworks wrap around Construction set and integrate with Functional set using a pre-defined scheme. You can think of them as templates for implementation of Construction set and integration logic.

Dependency Injection Framework

The integration scheme is usually built according to Convention over Configuration principle and can be annotation based, use XML documents and other conventions.

Except for different approaches to declaration of integration schemes, frameworks can also resolve dependencies at different stages. Some frameworks resolve dependencies at compile time while others postpone the resolution to runtime.

However different the dependency injection frameworks might be, they will usually have much in common:

  1. Inversion of control. This is the main characteristic of any framework in general.
  2. Pre-defined scheme for integration of Construction and Functional sets.
  3. Use fundamental dependency injection techniques under the hood: Constructor, Method and Field injection (potentially combined with runtime reflection).
  4. Pre-defined schemes for services lifecycle management. Frameworks will allow to alter the lifecycle of injected services in order to e.g. implement global instances that are being injected into all clients.
  5. Boiler-plate reduction.
  6. Frameworks might provide easier testing support.

While different dependency injection frameworks will have different characteristics, points one, two and three from the above list are common to all of them.

Dependency injection in Android:

The topic of Dependency Injection has been neglected for a very long time by Android official documentation and guidelines. Recently, however, it started to gain a lot of attention.

This is, undoubtedly, a welcome change and a sign of ongoing maturing of the platform, but a lack of good guidelines in this context causes a massive abuse of dependency injection frameworks, which is the opposite extreme that should be avoided.

In the remaining of this article, I will share with you several best practices that worked for me fro the past couple of years.

Since today the most common choice for dependency injection in Android is Dagger 2 dependency injection framework, the several code snippets that you’ll see will use its syntax.

Keep in mind, though, that these best practices are universal and apply equally to any other framework you might want to use.

Dependency injection in Android best practices:

The following list of best practices is my personal list of “rules of thumb” when it comes to dependency injection in Android.

1. Use constructor injection by default:

Clients should ask for all the required services through constructor arguments.

The advantages of constructor injection are:

  1. When constructor signature reflects all the services required by the client it makes the code more readable.
  2. Services are initialized at construction time and can’t be forgotten.
  3. Services injected through constructor can be finalized which ensures safe initialization and publication (important in context of multi-threading).
  4. Services injected into constructors are easy to mock in unit tests.

So, you should always use constructor injection, unless there is specific reasons not to do that.

2. Use dependency injection frameworks for top level components only:

When not abused, dependency injection frameworks provide a great deal of convenience in implementation of what I designated as Construction set. At the end of a day, the logic that wires together all the classes from Functional set must reside somewhere within your application, and it is where dependency injection frameworks come in very handy.

Somewhere within your application there must be boundaries between Construction set and Functional set of classes. These boundaries are the classes into which you inject dependencies using dependency injection framework.

In my opinion, top level components are the best candidates for becoming the aforementioned boundaries. There are two groups of top level components in Android:

  • Components which are being instantiated by Android framework: Application, Activity, Service, etc.
  • Components which are not top level hierarchically, but which are functionally decoupled from their parent component: Fragment, etc.

These classes should be the only ones that declare injectable fields for the framework.

3. Use Field Injection while injecting using frameworks:

All top level components listed in the previous paragraph are non-eligible for Constructor Injection. Since we can’t perform Constructor Injection, we must use either Method Injection or Field Injection.

In terms of encapsulation, Method Injection does not have any advantage in this case, but it does have some disadvantages:

  • The additional “setter” method pollutes client’s API
  • More boilerplate code required

Due to above reasons I recommend using Field Injection while injecting using a framework.

4. Don’t use the framework to inject into custom views:

If you need any service to be injected into a subclass of View, you have two options.

If the View can only be instantiated programmatically – use constructor injection.

However, even if it should be inflated from XML, don’t resolve to dependency injection frameworks. Use regular Method Injection instead.

For example, if you need to inject ImageLoader into a custom View, then instead of this:

public class SomeClient extends LinearLayout {
    @Inject ImageLoader mImageLoader; // will be injected using dependency injection framework

    public SomeClient(Context context) {


do this:

public class SomeClient extends LinearLayout {
    private ImageLoader mImageLoader;

    public SomeClient(Context context) {

    public void setImageLoader(ImageLoader imageLoader) {
        mImageLoader = imageLoader;


Advantages of using Method Injection in this case are:

  • Dependencies are visible at the API level.
  • Method Injection does not open door to Single Responsibility Principle violation.
  • No dependency on the framework.
  • Better performance.

First of all, the dependencies will appear as part of custom view’s API and readers of the source code will immediately understand that this specific custom View shows images. Such optimization for readability makes the system more easily maintainable in the long term.

Secondly, there are not many use cases in which sub-classes of View need additional dependencies. However, by injecting just one single dependency using a framework, you basically open a door for other injections.

Imagine that some data from SharedPreferences becomes required in custom View in order to e.g. fix a bug. You decide that it is a good idea to inject SharedPreferences into custom View directly. Doing this violates Single Responsibility Principle and makes your code worse, but this is exactly the kind of hacks we do under schedule pressure.

If you don’t use the framework, however, the fact that you need to actually work in order to provide these dependencies will give you a bit of time to think about whether providing them is a good design decision to start with.

Therefore, I recommend avoid using dependency injection frameworks for injection into custom views because such injection “backdoors” can reduce design quality and lead to long debug sessions. This is especially beneficial on big teams.

The third advantage of using Method Injection with custom Views is that you don’t couple the View to dependency injection framework.

Just imagine that few years from now you (or some other poor guy) need to replace the framework. The fact that you will probably have tens of Activities and Fragments to start with make it a big project. If you’ll have additional tens or hundreds of custom Views to handle, then it might bring you into suicidal mood.

The last (and, according to Donald Knuth, the least) advantage is performance.

One screen can contain one Activity, several Fragments and tens of custom Views. Bootstrapping this number of classes using dependency injection framework might degrade application’s performance. It is especially true for reflection based frameworks, but even Dagger carries some performance cost.

5. Don’t violate the Law of Demeter:

Law of Demeter, when applied in context of Dependency Injection, can be stated as “a client should be injected with the exact services that it needs”.

One very common violation of Law of Demeter in Android is when Context is injected into client, while what this client really needs is a reference to SharedPreferences (or reference to other system service, or any other reference retrieved from Context).

So, instead of this:

    public class SomeClient {
        private final SharedPreferences mSharedPreferences;

        public SomeClient(Context context) {
            mSharedPreferences = 
                    context.getSharedPreferences(PREFS_FILE_NAME, Context.MODE_PRIVATE);

do this:

    public class SomeClient {
        private final SharedPreferences mSharedPreferences;

        public SomeClient(SharedPreferences sharedPreferences) {
            mSharedPreferences = sharedPreferences;

Law of Demeter should be obeyed both when you use dependency injection framework and when you don’t.

Advantages of dependency injection without violations of Law of Demeter:

  • Client’s API reflects all its real dependencies
  • Client can be unit tested as “black box” – no need to read its code in order to find out what classes should be mocked
  • Unit testing is easier because you don’t need to mock services’ getter methods in order to mock the real service that the client uses

6. Differentiate between objects and data structures:

As discussed in this post by Matt Carroll, subclasses of Object class in Java can be divided into two sets: [object-oriented] objects and data structures.

Objects expose behavior. For example, UserManager class could expose authenticateUser method.

Data structures expose data. For Eample, User class could expose first name, last name, etc.

Dependency Injection in general, and the discussion in this post specifically, are both applicable to objects, but not applicable to data structures.

I would even go as far as saying that Construction set should not be aware of data structures at all. If you find yourself in position of referencing data structures in Construction set, then you’re probably already polluting Construction set with functional logic.


When it comes to Dependency Injection, there is no question whether to use it or not – it is one of the most beneficial architectural patterns in terms of code maintenance. However, there are no clear guidelines about how exactly dependency injection should be implemented in Android, which can lead to inefficient practices being employed.

In this post you learned the difference between dependency injection fundamental techniques and Dependency Injection architectural pattern and I shared with you my own set of best practices for dependency injection in Android.

In my experience, following these best practices yields a nicely decoupled code and very natural non-abusive integration of dependency injection frameworks into a workflow on Android.

As always, please leave your comments and questions below.

If you liked this post then you might also like a complete course about Dependency Injection in Android with Dagger 2. Get it now at a dicount price.

This article has 11 comments

  1. Jonathan Reply


    First of all, thanks for the excellent article. I have a question about the 4th best practice: “Use method injection for custom views”. Why it is not good to use a DI framework to inject services into the custom view? I couldn’t think of a good reason to not inject it with a framework. Thanks in advance for your time.


    • Vasiliy Reply

      Hello Jonathan and thanks for your question.
      You are right – this is the most controversial best practice and it requires justification. In order for all the readers to be able to understand the motivation behind this best practice, I added additional information in the post. Please re-read the respective section.
      Please let me know if this addition won’t clarify matters.

      • Carl Reply

        I think you could still grook it a little bit if you want to use constructor injection in your custom view to take advantage of onCreateView of AppCompatActivity and do the magic there.

        • Vasiliy Reply

          Hey Carl,
          I’m not sure I understand what you’re saying. Could you elaborate a bit?

  2. Android dev Reply

    Hi Vasiliy,

    Your post is very clear. Thanks for that.
    However I need to know whether dependency injection is possible in android library without any change needed at application side. As an android library I don’t have access of UI (Activity/Application) and not able to inject dependency.

    Thank you.

    • Vasiliy Reply

      Hello and thanks for your question,

      IMHO you should definitely use Dependency Injection architectural pattern while developing libraries, but not dependency injection framework.

      The downsides of using DI framework in libraries are:

      1) Increases library’s size
      2) Adds unnecessary dependency to the library
      3) Transitively adds unnecessary dependency to the client of the library
      4) Can lead to conflicting dependencies if the client of the library also uses the same DI framework, but different version

      I would do this instead:

      For external dependencies that need to be supplied by the client use constructor injection: when the client wants to use your library, it will need to instantiate some MyLibraryFacade class and pass all the required dependencies into its constructor.

      In order to wire the internal classes of the library that are being used by MyLibraryFacade, you can use either Pure Dependency Injection, or, in some cases, implement Service Locator pattern.

  3. Android dev Reply

    Thanks a lot Vasiliy for your quick support.

    I got your point but I would like to know more on this. As per my findings on Dagger-2 dependency injection is only possible during initialization of android components(Activity/Application/Fragment,etc). We can add modules & components classes in library but injection is only possible in Application/Activity.

    Is it correct understanding? What is your view on this?

    Thanks in advance.

    • Vasiliy Reply

      AFAIK, there is no such limitation on injection – you can use Dagger components in order to inject from any class and into any class. In fact, you can use Dagger even in non-Android projects.

      You CAN use Dagger in order to perform DI inside your library, but, IMHO, you SHOULDN’T do this due to reasons stated above.

  4. mujahid khan Reply

    “Method Injection does not open door to Single Responsibility Principle violation”
    only when class that relies on Method Injection, uses abstraction that gets concrete implementation via the method param.

    • Vasiliy Reply

      Hey Mujahid,
      If you mean that the injected objects should not open door to SRP violation by themselves then I strongly agree. That’s one of the reasons Context objects should not be passed around – any class that has an access to Context effectively has an access to the entire Android framework as well.

Leave a Comment

Your email address will not be published. Required fields are marked *