13
votes

For making things simple, suppose I want to inject EmailValidator from apache validators into my activity:

public class MainActivity extends FragmentActivity {

    @Inject
    EmailValidator emailValidator;

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

I have a MainModule class:

@Module
public class MainModule {

    @Provides
    public EmailValidator providesEmailValidator() {
        return EmailValidator.getInstance();
    }
}

and MainComponent interface:

@Singleton
@Component(modules = MainModule.class)
public interface MainComponent {

    EmailValidator getEmailValidator();
}

When trying to use my validator in activity, I'm getting a nullpointer exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean org.apache.commons.validator.routines.EmailValidator.isValid(java.lang.String)' on a null object reference

Obviously I'm missing something. I know that dagger creates component implementation for me. Should I use it? How?

If I do the following in my onCreate method:

        emailValidator = Dagger_MainComponent.create().getEmailValidator();

then everything works fine.

But I want to be able to use @Inject annotation anywhere (probably on setter/constructor instead of a field) instead.

What am I missing?

I did something similar with dagger1 and it worked. Of course I needed to call ObjecGraph.inject(this) in activity. What's the dagger2 equivalent?

EDIT:

Ok, so I've found a solution. If anyone will ever have such a problem, there are some snippets:

1) I've created an application class:

public class EmailSenderApplication extends Application {

    private MainComponent component;

    @Override
    public void onCreate() {
        super.onCreate();

        component = Dagger_MainComponent
                .create();

        component.inject(this);
    }

    public MainComponent component() {
        return component;
    }
}

2) In AndroidManifest.xml:

<application
        android:name=".EmailSenderApplication"
        ...

3) And finally, in the activity class where I want to inject some components those two ugly as hell lines:

component = ((EmailSenderApplication) getApplication()).component();
component.inject(this);
1
I can't call inject on my component. Also The Dagger_MainComponent syntax seems to have changed to just DaggerMainComponent. - Adam Johns

1 Answers

14
votes

Looks like you need to build your component as in:

component = Dagger_ MainComponent.builder()
        .mainModule(new MainModule())
        .build();

Typically, you do this in the onCreate method of your Application.

One good resource that may help you is the example apps in the Dagger 2 repo.

I also found this PR helpful, from a suggested update to Jake Wharton's u2020 sample app (from the main Dagger 2 Engineer). It gives a good overview of the changes you need to make when going from Dagger 1 to 2 and, apparently that's what he points people to as well.