Field Injection in Dagger2: DI (Day 2)

Photo by Mark Boss on Unsplash

Field Injection in Dagger2: DI (Day 2)

Understanding Framework Types

In our previous blog post, we discussed the basics of dependency injection and more specifically, constructor injection using Dagger. Today, we'll explore Field Injection, also known as Members Injection, and discuss when it should be used.

Introduction

Field Injection, a form of DI, comes into play when dependencies are directly injected into the fields of a class. This is particularly useful when working with Android's Activities and Fragments, where the instantiation of a class is out of the developer's control. In this blog post, we'll explore Field Injection in detail and learn how to implement it using Dagger2.

Field Injection in Action

Let's apply field injection in our project which we created in the previous post. The first change that we need to make is to annotate our ComputeLayer variable with @Inject. This annotation tells Dagger that we need to field inject it.

@Inject
lateinit var computation : ComputeLayer

Please note that the variable annotated with @Inject cannot be private. This is because it will eventually be used by other classes that Dagger creates for dependency injection.

Once done, the code should look something like this:

class MainActivity : AppCompatActivity() {
    var calculate : Button? = null
    var TAG = this.javaClass.canonicalName

    @Inject
    lateinit var computation : ComputeLayer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        calculate = findViewById(R.id.calculate_sum)

        val component = DaggerComputeComponent.create()
        component.inject(this)

        calculate?.setOnClickListener {
            computation.add(1,1)
            Log.e(TAG, "Button click detected")
        }
    }
}

Notice that instead of injecting each variable one by one, we have simply told Dagger that we need the field injected in our activity with the following code:

val component = DaggerComputeComponent.create()
component.inject(this)

The inject method looks like this:

void inject (MainActivity mainActivity);

The benefit of using field injection is that we can use multiple member variables, instead of calling a create provision method for each of the objects.

We could have used field injection for our ComputeLayer class as well, but it's always advisable to use field injection only in cases when method injection is not available. This is often the case with Activities and Fragments (Framework Types), where we do not create the class ourselves (as you don’t have a constructor available for these classes).

And that's it! If you run the app again, it'll work just as it used to, but with more readable code.

Conclusion

Field Injection is a powerful technique that allows for cleaner, more modular code by delegating the responsibility of providing dependencies to Dagger. However, it's not a one-size-fits-all solution. It's best suited for situations where Constructor Injection is not possible, such as with Android's Activities and Fragments.

In this blog post, we've explored how to implement Field Injection using Dagger2. We've seen how to annotate fields for injection, how to instruct Dagger to inject dependencies, and when it's appropriate to use Field Injection. As with any tool, the key to effectively using Field Injection is understanding when and where to use it.

In our next blog post, we'll dive deeper into field injection and see how such dependency injection makes our code modular. We'll also try to visualize our dependency graph and understand what exactly is a Directed Acyclic Graph or DAG. Stay tuned!