Dagger2 - null instead of injected object

18,227

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.

Share:
18,227

Related videos on Youtube

slnowak
Author by

slnowak

https://slnowak.wordpress.com

Updated on June 04, 2022

Comments

  • slnowak
    slnowak about 2 years

    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
    slnowak over 9 years
    I figured it out. Because of useful links, I'm accepting this answer :)
  • gMale
    gMale over 9 years
    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.
  • slnowak
    slnowak over 9 years
    Yeah, I know about it, but thanks. ;) The missing part Was component.inject(this)
  • fakataha
    fakataha over 9 years
    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.
  • gMale
    gMale over 9 years
    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.
  • Accountant م
    Accountant م over 5 years
    first link is broken, is there any replacement for it ?