Interview

10 Dagger Android Interview Questions and Answers

Prepare for your Android interview with this guide on Dagger. Learn about dependency injection and enhance your development skills.

Dagger is a popular dependency injection framework for Android that helps developers manage and inject dependencies efficiently. By automating the process of dependency resolution, Dagger simplifies code maintenance and enhances modularity, making it a crucial tool for building scalable and testable Android applications. Its integration with Android’s architecture components further streamlines development workflows.

This article offers a curated selection of interview questions focused on Dagger for Android. Reviewing these questions will deepen your understanding of dependency injection principles and prepare you to discuss Dagger’s implementation and benefits confidently in your next technical interview.

Dagger Android Interview Questions and Answers

1. Describe the difference between @Inject, @Provides, and @Binds annotations. Provide examples of when to use each.

In Dagger Android, @Inject, @Provides, and @Binds annotations manage dependencies, each serving distinct purposes.

  • @Inject: Used to request dependencies, applicable to constructors, fields, or methods. When on a constructor, it instructs Dagger on instance creation.

Example:

public class Engine {
    @Inject
    public Engine() {
        // Constructor
    }
}
  • @Provides: Used in Dagger modules to specify how to create instances of a type.

Example:

@Module
public class CarModule {
    @Provides
    Engine provideEngine() {
        return new Engine();
    }
}
  • @Binds: Binds an implementation to an interface, more efficient than @Provides by avoiding new instance creation.

Example:

@Module
public abstract class CarModule {
    @Binds
    abstract Engine bindEngine(PetrolEngine engine);
}

2. Write a simple Dagger module that provides an instance of a NetworkService class.

A Dagger module, annotated with @Module, defines how to provide instances of certain types. The @Provides annotation within the module specifies instance creation, useful for managing dependencies like a singleton NetworkService.

Example:

import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;

@Module
public class NetworkModule {

    @Provides
    @Singleton
    public NetworkService provideNetworkService() {
        return new NetworkService();
    }
}

Here, NetworkModule is a Dagger module, and provideNetworkService is annotated with @Provides and @Singleton, ensuring a singleton instance of NetworkService.

3. What is the purpose of the @Singleton annotation in Dagger, and how does it affect the lifecycle of provided objects?

The @Singleton annotation in Dagger indicates a single instance of a provided object should be created and shared. It ensures only one instance of a class is created and used throughout the application’s lifecycle, useful for objects like database connections or network clients.

Example:

@Module
public class NetworkModule {

    @Provides
    @Singleton
    public Retrofit provideRetrofit() {
        return new Retrofit.Builder()
                .baseUrl("https://api.example.com")
                .build();
    }
}

@Component(modules = {NetworkModule.class})
@Singleton
public interface AppComponent {
    Retrofit getRetrofit();
}

In this example, NetworkModule provides a Retrofit instance annotated with @Singleton, ensuring the same instance is used whenever injected.

4. Explain the role of Component in Dagger and how it interacts with modules.

A Component in Dagger is an interface acting as a bridge between dependency providers (modules) and consumers (injected classes). It manages the lifecycle and scope of dependencies, using modules to fulfill dependency requirements.

Example:

// Define a module to provide dependencies
@Module
class NetworkModule {
    @Provides
    NetworkService provideNetworkService() {
        return new NetworkService();
    }
}

// Define a component that uses the module
@Component(modules = {NetworkModule.class})
interface AppComponent {
    void inject(MainActivity mainActivity);
}

// Class that requires the dependency
public class MainActivity extends AppCompatActivity {
    @Inject
    NetworkService networkService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DaggerAppComponent.create().inject(this);
        // Now networkService is available for use
    }
}

Here, NetworkModule provides an instance of NetworkService, and AppComponent specifies its use to fulfill dependency requests.

5. How would you inject dependencies into an Android Activity using Dagger? Provide a code example.

To inject dependencies into an Android Activity using Dagger, define a module providing the dependencies, create a component interface connecting the module to the injection target, and use the component to inject dependencies into the Activity.

Example:

// Define a module
@Module
public class AppModule {
    @Provides
    public SomeDependency provideSomeDependency() {
        return new SomeDependency();
    }
}

// Create a component interface
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(MainActivity activity);
}

// Define the dependency
public class SomeDependency {
    public void doSomething() {
        // Implementation
    }
}

// Inject dependencies into the Activity
public class MainActivity extends AppCompatActivity {
    @Inject
    SomeDependency someDependency;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize Dagger
        DaggerAppComponent.create().inject(this);

        // Use the injected dependency
        someDependency.doSomething();
    }
}

6. Write a Dagger setup that includes a subcomponent for injecting dependencies into a Fragment.

To set up Dagger with a subcomponent for injecting dependencies into a Fragment, define the necessary components, modules, and the subcomponent itself.

First, create a module providing the dependencies:

@Module
public class AppModule {
    @Provides
    public SomeDependency provideSomeDependency() {
        return new SomeDependency();
    }
}

Next, define the main component including the module and declaring the subcomponent factory:

@Component(modules = {AppModule.class})
public interface AppComponent {
    FragmentSubcomponent.Factory fragmentSubcomponent();
}

Then, create the subcomponent for the Fragment:

@Subcomponent
public interface FragmentSubcomponent {
    void inject(MyFragment fragment);

    @Subcomponent.Factory
    interface Factory {
        FragmentSubcomponent create();
    }
}

In your Fragment, inject the dependencies using the subcomponent:

public class MyFragment extends Fragment {
    @Inject
    SomeDependency someDependency;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        ((MyApplication) context.getApplicationContext())
            .getAppComponent()
            .fragmentSubcomponent()
            .create()
            .inject(this);
    }
}

7. Explain the concept of multibindings in Dagger and provide an example of how to use them.

Multibindings in Dagger allow binding multiple objects into a single collection, like a set or map, useful for injecting a collection of objects extendable by different modules.

To use multibindings, use @IntoSet or @IntoMap annotations. @IntoSet adds an object to a set, while @IntoMap adds an object to a map with a specific key.

Example:

@Module
public abstract class AnimalModule {

    @Binds
    @IntoSet
    abstract Animal bindDog(Dog dog);

    @Binds
    @IntoSet
    abstract Animal bindCat(Cat cat);
}

@Component(modules = AnimalModule.class)
public interface AnimalComponent {
    Set<Animal> getAnimals();
}

public class Main {
    public static void main(String[] args) {
        AnimalComponent component = DaggerAnimalComponent.create();
        Set<Animal> animals = component.getAnimals();
        animals.forEach(animal -> System.out.println(animal.getName()));
    }
}

In this example, AnimalModule binds two implementations of Animal, Dog and Cat, into a set, which AnimalComponent provides.

8. Explain the concept of scopes and subcomponents in Dagger. Provide an example of how they are used.

In Dagger, scopes define the lifecycle of dependencies, ensuring a single instance is created and shared within a defined scope. Common scopes in Android include @Singleton, @ActivityScope, and @FragmentScope.

Subcomponents create a hierarchical structure of components, allowing granular control over dependency injection and enabling module and dependency reuse within different application parts. Subcomponents inherit and extend bindings from parent components.

Example:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {}

@ActivityScope
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComponent {
    void inject(MainActivity mainActivity);
}

@Module
public class ActivityModule {
    @Provides
    @ActivityScope
    SomeDependency provideSomeDependency() {
        return new SomeDependency();
    }
}

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    ActivityComponent newActivityComponent(ActivityModule activityModule);
}

In this example, ActivityScope manages the lifecycle of dependencies within an activity, and ActivityComponent is a subcomponent of AppComponent.

9. Explain the use of Lazy and Provider in Dagger. When would you use each?

In Dagger, Lazy and Provider control the instantiation and lifecycle of dependencies.

  • Lazy: Delays dependency creation until needed, improving performance and reducing memory usage. Injecting a Lazy<T> delays instance creation until get() is called.
  • Provider: Creates multiple instances of a dependency, unlike Lazy, which provides a single instance. Useful for fresh instances of stateful objects.

Example:

import javax.inject.Inject;
import javax.inject.Provider;
import dagger.Lazy;

public class Example {
    @Inject
    Lazy<HeavyObject> heavyObjectLazy;

    @Inject
    Provider<LightObject> lightObjectProvider;

    public void useLazy() {
        // HeavyObject is created only when get() is called
        HeavyObject heavyObject = heavyObjectLazy.get();
        heavyObject.doSomething();
    }

    public void useProvider() {
        // A new instance of LightObject is created each time get() is called
        LightObject lightObject1 = lightObjectProvider.get();
        LightObject lightObject2 = lightObjectProvider.get();
        lightObject1.doSomething();
        lightObject2.doSomething();
    }
}

10. What are qualifiers in Dagger, and how do they help in dependency injection? Provide an example.

Qualifiers in Dagger are annotations that differentiate between multiple objects of the same type, essential when multiple implementations of an interface or instances of a class exist. Qualifiers are custom annotations used to annotate dependencies and injection points.

Example:

import javax.inject.Qualifier;
import javax.inject.Inject;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@interface DatabaseType {
    String value();
}

class Database {
    private String type;

    @Inject
    public Database(@DatabaseType("SQL") String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

@Module
class DatabaseModule {
    @Provides
    @DatabaseType("SQL")
    String provideSQLDatabase() {
        return "SQL Database";
    }

    @Provides
    @DatabaseType("NoSQL")
    String provideNoSQLDatabase() {
        return "NoSQL Database";
    }
}

@Component(modules = DatabaseModule.class)
interface DatabaseComponent {
    Database getDatabase();
}

public class Main {
    public static void main(String[] args) {
        DatabaseComponent component = DaggerDatabaseComponent.create();
        Database database = component.getDatabase();
        System.out.println(database.getType()); // Outputs: SQL Database
    }
}
Previous

10 IBM Integration Bus Interview Questions and Answers

Back to Interview
Next

10 Android Debug Bridge Interview Questions and Answers