Mobile Development 19 min read

Understanding Dagger2 Dependency Injection in Android with Practical Code Examples

This article explains the concepts and practical usage of Dagger2 for compile‑time dependency injection in Android, illustrating why hard‑coded object creation is problematic, how constructor, setter, and interface injection solve these issues, and providing step‑by‑step code samples for modules, components, scopes, and qualifiers.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Understanding Dagger2 Dependency Injection in Android with Practical Code Examples

Dagger2 is a fully static, compile‑time dependency injection framework for Java and Android, created by Square and now maintained by Google, which eliminates the performance and maintenance problems caused by reflection‑based DI solutions.

The article begins with a coffee‑shop analogy to demonstrate the drawbacks of hard initialization (hard‑coding object creation) and how such tightly coupled code becomes difficult to modify when business requirements change.

Key example classes are presented:

public class CoffeeMachine {
    private CoffeeMaker maker;
    public CoffeeMachine(Cooker cooker){
        maker = new SimpleMaker(cooker);
    }
    public String makeCoffee(){
        return maker.makeCoffee();
    }
}

public interface CoffeeMaker {
    String makeCoffee();
}

public class SimpleMaker implements CoffeeMaker {
    private Cooker cooker;
    @Inject
    public SimpleMaker(Cooker cooker){
        this.cooker = cooker;
    }
    @Override
    public String makeCoffee(){
        return cooker.make();
    }
}

public class Cooker {
    String name;
    String coffeeKind;
    public Cooker(String name, String coffeeKind){
        this.name = name;
        this.coffeeKind = coffeeKind;
    }
    public String make(){
        return name + " make " + coffeeKind;
    }
}

To avoid hard‑coded dependencies, Dagger2 offers three injection styles:

public class CoffeeMachineWithInjection implements InjectMaker {
    private CoffeeMaker maker;
    // Constructor injection
    public CoffeeMachineWithInjection(CoffeeMaker maker){
        this.maker = maker;
    }
    // Setter injection
    public void setMaker(CoffeeMaker maker){
        this.maker = maker;
    }
    // Interface injection
    @Override
    public void injectMaker(CoffeeMaker maker){
        this.maker = maker;
    }
    public String makeCoffee(){
        return maker.makeCoffee();
    }
}

public interface InjectMaker {
    void injectMaker(CoffeeMaker maker);
}

The essential Dagger2 annotations are introduced:

@Inject – marks constructors or fields that Dagger can provide.

@Provides – placed on methods inside a @Module to supply objects that cannot be constructed directly.

@Module – groups provider methods.

@Component – bridges modules and injection targets.

Gradle configuration for Dagger2:

apply plugin: 'com.neenbedankt.android-apt'

buildscript {
    repositories { jcenter() }
    dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' }
}

dependencies {
    apt 'com.google.dagger:dagger-compiler:2.0'
    compile 'com.google.dagger:dagger:2.0'
}

A simple Android activity demonstrates injection:

public class OriginActivity extends Activity implements View.OnClickListener {
    @Inject CoffeeMachine coffeeMachine;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);
        SimpleComponent component = DaggerSimpleComponent.builder()
                .simpleModule(new SimpleModule())
                .build();
        component.inject(this);
    }
    // ... UI handling code ...
}

@Module
public class SimpleModule {
    @Provides
    Cooker provideCooker(){
        return new Cooker("James","Espresso");
    }
}

@Component(modules = SimpleModule.class)
public interface SimpleComponent {
    void inject(OriginActivity activity);
}

Advanced topics cover @Qualifier to disambiguate multiple providers of the same type and @Scope to create scoped (local singleton) instances, illustrated with two different Cooker providers (@A and @B) and a custom @PerActivity scope.

The article concludes that while the basic annotations are straightforward, mastering Dagger2 in real projects requires understanding generated code, component hierarchies, and proper scoping, which will be explored in future posts.

JavaAndroidannotationsdependency injectionDIDagger2
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.