Sunday 20 December 2015

Lesson 1 - Dagger2 -Dagger 2 scoped modules and components

Dependency Injection - scopes and dependent components with Dagger 2 tutorial



Welcome to lesson 1. Understanding Dagger 2 can be challenging.  I have to admit there is a lot of boilerplate code.  Using Dagger2 for android though is better then other dependency injection (DI) frameworks because it uses no reflection, which is slow on Android.  It’s the best we have right now so lets accept it and jump right into.  We will be looking at understanding scoped providers as well as scoped components.  


Requirements for this tutorial:

   1.     Android Studio


Set up:

Create a empty android activity in Android studio by going to fileànew ànew project:
Set the minimum SDK to 16 if you wish or leave it as is.


The rest you can figure out or leave as is and hit finish.
In build.gradle in your app module ensure you have the following dependencies :

compile 'com.google.dagger:dagger:2.0'
apt 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'

Great, sets up done now onto the juicy stuff.

What does it mean to scope a component:
In Dagger 2 the scope idea is really about keeping a single instance of a dependency/class only as long as its scope exists. This avoids a big memory footprint. Who wants classes hanging around for the lifetime of your app when there only needed once or twice ? get it ?

 That’s right ! if your not using scoped components your objects are most likely sitting in memory once dagger provided.  Let’s do something about it.


Usually bloggers on this subject work with application scope vs activity scope. Let us be a bit different  approach, it might help us understand scoped injections easier.

The Story:
Let’s use butter and sandwiches in our example to follow.  There are many kinds of butter. My favorites are cashew nut butter, almond nut butters not bad either.  Sandwiches need butter (to taste good, duh). So our Sandwiches will depend on a butter.  Once we have a butter we can make a sandwich such as a almond butter Sandwich or cashew nut butter Sandwich – you get the drift.


My package structure will look like below but for now just worry about the butter and sandwiches – yummy:




The butter.java class is just an abstract base class, you can ignore it. But it just simply prints out which butter we are using:

public abstract class Butter {

    @Override

    public String toString() {

        return getClass().getSimpleName();

    }

}
 

The two classes AlmondButter and CashewButter are empty and just extend from Butter.

AlmondButter.java:
public class AlmondButter extends Butter {}


Notice each package contains a module; SandwichModule and ButterModule.  It’s just placed here for consistency.  Let’s take a look at the butterModule.java:

@Module
public class ButterModule {
   
   
@Provides
    @ButterScope
   
AlmondButter ProvideAlmondButter(){
       
return new AlmondButter();

    }

   
@Provides
    @ButterScope
   
CashewButter ProvideCashewButter(){
       
return new CashewButter();

    }
}

All im doing here is telling Dagger that I want to provide an almondButter or a cashewButter spread.  It does nothing else. 

Lets see the sandwichModule.java now:

@Module

public class SandwichModule {



    @Provides

    @SandwichScope

    CashewSandwich ProvidesCashewSandwich(CashewButter butter){

        return new CashewSandwich(butter);

    }



    @Provides

    @SandwichScope

    AlmondSandwich ProvidesCashewSandwich(AlmondButter butter){

        return new AlmondSandwich(butter);

    }

}

Again, we are just telling our dagger component that we will be providing the AlmondSandwich or cashewSandwich. 

But how do we get the butter ? How does it get passed in ? And what are these two scopes “SandwichScope and ButterScope” ?

Lets get to the heart of the discussion, Dagger 2 components.

Components are responsible for the actual injection. It’s the bridge between modules and the @injection annotation or command.  Components talk to modules to perform the dependency injections. 

Let’s have a look at my project structure again but this time take a look at the components and scopes:



Custom Scopes and scoped providers

Actually custom scope annotations (like ButterScope and SandwitchScope) in dagger 2 help us to create scope providers!
Scope providers are created when we annotate our custom scope onto the provider and onto a component that uses the module the provider is in. 

Lets look at ButterScope & SandwichScope respectively:

Butterscope.java:
 Scope

    @Retention(RetentionPolicy.RUNTIME)

    public @interface ButterScope { }

SandwichScope.java:
@Scope

@Retention(RetentionPolicy.RUNTIME)

public @interface SandwichScope {}

Just like how dagger uses the singleton scope we are defining our own here instead. We are creating our own annotation tag here.  When we annotate a provider with custom scope (that matches the scope of the component) we are telling dagger to only create/provide a single instance of that dependent class for the lifetime of the scope.

If we look in SandwichModule.java notice there is a annotation of "SandwichScope" on the provider methods. This means that when i actually call @Inject CashewSandwich and @Inject CashewSandwich2 in a class, it will always inject the same object. If i did not annotate the provider with a scope then calling inject would have injected 2 separate instances of CashewSandwich.  So custom scopes are useful for having singletons scoped !


Shut up and get to scoped components already !!

Take a look at ButterComponent.java:
/**

remember,Components connect @Modules With @Inject

 */



@ButterScope

@Component(modules={ButterModule.class})



public interface ButterComponent {

//expose these for whatever class depends on butter

     AlmondButter ProvideAlmondButter();

     CashewButter ProvideCashewButter();

}

The ButterComponent will be a dependency for a sandwich.  We have to declare what the butterComponent can provide, here its ProvideAlmondButter and ProvideCashButter.

A Sandwich component would depend on the butterComponent:

sandwichComponent.java:

@SandwitchScope
@Component(dependencies = ButterComponent.class, 
modules = SandwichModule.class)
public interface SandwichComponent {
    CashewSandwich ProvideCashewSandwitch();

    void inject (MainActivity mainactivity);
}

Notice I declare that butterComponent.class is a dependency.  This is how in the SandwichModule.java we are able to get the butter provided to us earlier.

It's important to note that i've also created a inject method here. This will allow our MainActivity class to call the inject method. It allows the MainActivity to use the annotation @Inject.  It's daggers way of helping us use the @Inject annotation instead of having to individually reference each dependent item we want.  Well see this how this works later on. 

Now we’ve figured out how to make dependent components, lets move forward.

Let’s now go to our mainActivity and see how we can use all this and create scopes:

public class MainActivity extends AppCompatActivity {



    private final String TAG = getClass().getSimpleName();

    @Inject

    AlmondButter someAlmondButter;

    @Inject

    CashewSandwich sandwich;



    SandwichComponent sandwichComponent;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);



        /*create the dependent butter for the sandwich here*/

        ButterComponent butterComponent=DaggerButterComponent.builder().

                butterModule(new ButterModule()).build();

        /*create a scope sandwichcomponent here */



        sandwichComponent=DaggerSandwichComponent.builder().sandwichModule(new SandwichModule()).

                butterComponent(butterComponent)

                .build();

        //finally we have a sandwichComponent, lets inject our dependencies

        sandwichComponent.inject(this);



        Log.v(TAG,sandwich.toString());

        Log.v(TAG,someAlmondButter.toString());

    }



    @Override

    protected void onDestroy() {

        super.onDestroy();

        //not necessary but it clearly shows the scope being tied to lifecycle of activity

        sandwichComponent=null;

    }

}

As you can see we build the sandwichComponent and use butterComponent as a dependent.  We store it as a class variable and it will be garbage collected when the activity is destroyed.  This is how you make a scoped graph.

Dagger 2 Lesson 2 @Inject on constructors as providers

Source: github: https://github.com/j2emanue/dagger2_scope_demo

“Creativity is intelligence having fun.” – Albert Einstein

Tuesday 8 December 2015

Lesson 2 -dagger2 - Dagger 2 provider object with @Inject annotation

Dagger2 – Providing Object’s by tagging Constructor with @Inject tutorial


Welcome to lesson 2. Let’s continue on using dagger2 by using our lesson 1 example of butter and sandwiches in http://j2emanue.blogspot.com/

In Dagger2 we can provide dependencies using modules registered in components. This much we know from lesson 1.  Dagger2 also allows for providing an object by tagging its constructor with @Inject. 

Let’s take our story from lesson 1 further and say now we want to add a utensil to the story.  A knife for our spread.  So Let’s create a knife class. My directory structure will now look like this after creating a utensils package:


The Knife.java class itself will look like this:

public class Knife {
    int count=0;
    
    @Inject
    public Knife(){
        System.out.println("a spreading knife has been created");
    };


    @Override
    public String toString() {
        return "Knife{" +
                "count=" + ++count +
                '}';
    }
}



What I’m about to show you is how we can inject knife into our mainActivity without putting it in any module. We wont reference it in any component either.  Placing @Inject on a constructor makes it detectable to Dagger2. Notice that our knife constructor is annotated with @Inject.  It becomes automatically unscoped but ready to be injected into our mainactivity. Let’s see what our mainActivity would look like now that we have a knife:

public class MainActivity extends AppCompatActivity {



 private final String TAG = getClass().getSimpleName();



 //@Inject

 //AlmondButter someAlmondButter;

 @Inject

 CashewSandwich sandwich;



 @Inject

 CashewSandwich sandwich2;



 @Inject

 Knife mKnife;



 @Inject

 Knife mKnife2;



 SandwichComponent sandwichComponent;



 @Override

 protected void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  setContentView(R.layout.activity_main);



  /*create the dependent butter for the sandwich here*/

  ButterComponent butterComponent = DaggerButterComponent.builder().

  butterModule(new ButterModule()).build();

  /*create a scope sandwichcomponent here */



  sandwichComponent = DaggerSandwichComponent.builder().sandwichModule(new SandwichModule()).

  butterComponent(butterComponent)

  .build();

  //finally we have a sandwichComponent, lets inject our dependencies

  sandwichComponent.inject(this);



  Log.v(TAG, " first:" + sandwich.toString());

  Log.v(TAG, "second:" + sandwich2.toString());

  Log.v(TAG, "first knife:" + mKnife.toString());

  Log.v(TAG, "second knife" + mKnife2.toString());

 }
}

Actually we have two knife classes which are injected.  Once we have a component build in onCreate(), those classes become available to us. 


Keep in mind, the knife class is unscoped right now. That means, each time we call @inject to supply us with a knife, we are creating a brand new object. If we wanted to keep the same object we would use the scope of the component (in our case @SandwichScope) and mark the class (NOT the constructor) with this scope. Lets see how we can make our knife.java class scoped:


@SandwitchScope

public class Knife {

    int count=0;



    @Inject

    public Knife(){

        System.out.println("a spreading knife has been created");

    };

    

    @Override

    public String toString() {

        return "Knife{" +

                "count=" + ++count +

                '}';
    }

}

Notice the top line has a scope annotation. This makes our knife class be a singleton within the sandwichScope.  Since our component in mainactivity is a sandwichComponent tagged with @SandwichScope, the knife object becomes a singleton for as long as this component exists.

I hope this information was informative.


 In conclusion I would think modules and components to provide objects is a more cleaner way of organizing your project then marking a constructor with @Inject. It would be difficult to know a class is provided easily otherwise. Why ? You would have to search your code base under each class and find out which one has a constructor with @Inject. Thats a code smell.  With modules we can simply search the module file to find all providers (especially if modules are package specific). 


If I have seen further than others, it is by standing upon the shoulders of giants. - Isaac Newton



Tuesday 1 December 2015

Gradle Dependency scopes - Lesson 2

Gradle dependency scopes for Android




A bit of history on why i chose this topic.  I ran into an issue with the android 65k limit (your code can have a max of 65k methods).  Thought of using proguard to strip unused methods but it slowed down debug builds. Developers were left waiting a long time just compile and run.  Tried multiDex and it slows down your build (at least in previous android gradle schemes).  MultiDex might work for you but i'd like to demo how we can lower method counts before having to go into that direction.

The best approach to keep the method count down would be to not even have the methods in the first place.  Don't use unnecessary methods, right ? But how ? I'll keep this as short as possible and you can get the drift and carry on.

Dependency types  


  • Provided
  • Compile
  • Package
  • Apt (for android apt plugin)

Provided:
Have you ever looked in a gradle.build file for android and seen the word provided as part of the depenencies. Like this:




This means that we only need the dependency for compilation. The end user does not need it, so drop it after we compile.  This can save us some unnecessary methods. 


Compile:
You've seen this one all the time as its the most used. It tells gradle we need this library all the time, at compile and run time.  Keep it. 

Package: 
This would be for libraries you want only when packaging. 

Apt:
As a side note, the android-apt plugin also has a scope we can use called apt. You might have seen it before when defining dagger dependencies for example. It looks like this in gradle dependencies closure:


apt 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'

What is this apt scope ? Its very similar to provide actually. In most cases it's the same effect.  One prime difference is when you use the provided scope, the generated code is not available to the IDE. For example, let's change the dagger compiler to have a provided scope:


provided 'com.google.dagger:dagger-compiler:2.0'
provided 'org.glassfish:javax.annotation:10.0-b28'

Now if we sync gradle, the IDE will not be able to find your dagger component (ie. daggers boilerplate generated code) and you'll get an error of something like this at compile time:


error: cannot find symbol  
return DaggerMyComponent.builder() 

Using apt allows the IDE to see the generated code.

Conclusion:
If you find yourself looking for a way to minimize method calls or creating a library, have this strategy in mind at design time.  Your users will likely appreicate the consideration. 

Truth is ever to be found in simplicity, and not in the multiplicity and confusion of things. - Isaac Newton