anil
anil

Reputation: 331

Dagger 2 Getting null object reference on create method

I can't understand what wrong I am doing here

Splash Activity :

public class SplashActivity extends BaseActivity implements SplashView {

    @Inject
    SplashPresenter presenter;

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

Component :

@Component(modules = SplashModule.class)
public interface AppComponent {
    SplashWithDiPresenter getSplashWithDiPresenter();
}

Splash Module :

@Module(includes = RetrofitModule.class)
public class SplashModule {

    @Provides
    SplashPresenter provideSplashPresenter(final SplashInteractorImpl interactor){
        return new SplashPresenterImpl(interactor);
    }

    @Provides
    SplashInteractor providesSplashInteractor(final ApiInterface apiInterface){
        return new SplashWithDiInteractorImpl(apiInterface);
    }
}

inside application class called this method in onCreate()

private void createComponent() {
        appComponent = DaggerAppComponent.builder()
                .splashModule(new SplashModule())
                .build();

    }

Getting null object reference on Splash activity on create method

-> presenter.getAppVersion();

Upvotes: 2

Views: 1380

Answers (2)

rahul.taicho
rahul.taicho

Reputation: 1379

Ideally you should look at using subcomponents for these use cases for injecting Android Components(Activities, Fragments, Services...). It's pretty simple and avoids coupling Injector Components with Android components enabling testing of these classes and switching of components for Espresso tests.

Add dagger-android deps to your project (com.google.dagger:dagger-android-support:2.x, com.google.dagger:dagger-android-processor:2.x)

And then make an abstract DepsModule module, for example -

@Module
public abstract class DepsModule {

    @PerActivity
    @ContributesAndroidInjector(modules={SplashModule.class})
    SplashActivity provideSplashInjector()
}

And change you App Component to include AndroidSupportInjectionModule.class & DepsModule.class and you should remove SplashModule.classs from the list to avoid rebinding errors.

Now its as easy as having a DispatchingAndroidInjector<Activity> instance injected to you App class and implementing HasActivityInjector interface to return the dispatching injector.

Now in SplashActivity before invoking super.onCreate() call AndroidSupportInjection.inject(this)

@ContribbutesAndroidInjector automatically tells dagger to create a sub-component for SplashActivity and bind the injector factory with DispatchingAndroidInjector<Activity> removing the need for boilerplate sub-component classes

And other sub-component installations for different activities can be added to DepsModule to enable injecting them in a similar way.

This also helps in scope segregation as exposing a splash activity's bindings to the entire app component is not really good

Hope I could help. You can visit the dagger 2 android docs for more info on using Dagger 2

Upvotes: 0

Dmitry
Dmitry

Reputation: 2526

You have injected your application dependencies and now you need to do the same with SplashActivity dependencies. So you need to create a new component for your activity, lets say SplashComponent, and add inject method to it like this:

@PerActivity
@Component(modules = SplashModule.class, dependencies = AppComponent.class)
public interface SplashComponent {
    public void inject(SplashActivity activity);
}

And then in your SplashActivity in the onCreate method add injection like this:

public class SplashActivity extends BaseActivity implements SplashView {

    @Inject
    SplashPresenter presenter;

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

        DaggerSplashComponent.builder()
                .appComponent(getAppication().getAppComponent())
                .splashModule(new SplashModule())
                .build()
                .inject(this);

        presenter.getAppVersion();
    }
}

Note, that you need to call your presenter's method only after you have injected your dependencies with inject method!

Upvotes: 2

Related Questions