16

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);
slnowak
  • 1,839
  • 3
  • 23
  • 37
  • I can't call `inject` on my component. Also The Dagger_MainComponent syntax seems to have changed to just DaggerMainComponent. – Adam Johns Jun 15 '15 at 15:55

1 Answers1

14

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.

lkogs
  • 53
  • 10
gMale
  • 17,147
  • 17
  • 91
  • 116
  • I figured it out. Because of useful links, I'm accepting this answer :) – slnowak Feb 26 '15 at 17:42
  • Glad you got it fixed! From your edits above, it looks like you had a case where none of your module constructors require constructor arguments. When that's true, the component will have a `create` method for you to use instead. Chances are though, after a while, you will need to pass your application in to one of those modules and when that happens, you'll have to fall back to using the builder as described, above. – gMale Feb 27 '15 at 22:24
  • Yeah, I know about it, but thanks. ;) The missing part Was component.inject(this) – slnowak Feb 27 '15 at 23:20
  • 1
    Could anyone explain why this is? I corrected this in my app through trial and error but don't quite see the reasoning. In my case, I had an activity that built the component and injected itself. Then a Controller would have been injected to the Activity but was always null until I made another inject into the Component with the Controller as a param. – fakataha Mar 03 '15 at 20:10
  • In my case, I have injected dependencies in my application object so I must inject. Your case sounds different but the good news is, since the code is generated, you can just trace through the particular `inject` call that you're asking about in the IDE and see *exactly* why it's needed. – gMale Mar 03 '15 at 23:05
  • first [link](https://github.com/google/dagger/blob/master/examples/android-simple/src/main/java/com/example/dagger/simple/DemoApplication.java#L41) is broken, is there any replacement for it ? – Accountant م Mar 15 '19 at 02:47