Dennis Dennis - 10 days ago 7
Android Question

I don't know why the object injected by dagger2 is null in presenter

I don't know why loginResponseHandler of MainRankPresenter.java injected by dagger2 is null in MainRankPresenter.
I just want to inject to field for field injection.
Should I do other way instead field injection?
please, Let me know how to resolve it.

BBBApplication.java

public class BBBApplication extends MultiDexApplication
{
...
@Override
public void onCreate() {
super.onCreate();

initAppComponent();
}

private void initAppComponent() {
this.appComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
}

public static BBBApplication get(Context ctx) {
return (BBBApplication) ctx.getApplicationContext();
}
public AppComponent getAppComponent() {
return this.appComponent;
}
...
}


AppModule.java

@Module
public class AppModule {
private BBBApplication application;

public AppModule(BBBApplication application) {
this.application = application;
}

@Provides
@Singleton
public Application provideApplication() {
return this.application;
}

@Provides
@Singleton
public Resources provideResources() {
return this.application.getResources();
}

@Provides`enter code here`
@Singleton
public SharedPreferences provideSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(this.application);
}
}


AppComponent.java

@Singleton
@Component(modules = {AppModule.class, ServiceModule.class})
public interface AppComponent {
RankFragmentComponent plus(RankFragmentModule module);

Application application();
Resources resources();
}


RankFragmentModule.java

@Module
public class RankFragmentModule {

private RankFragment rankFragment;

public RankFragmentModule(RankFragment rankFragment) {
this.rankFragment = rankFragment;
}

@Provides
@ActivityScope
public LoginResponseHandler provideLoginResponseHandler() {
return new LoginResponseHandler(this.rankFragment);
}

@Provides
@ActivityScope
// @Named("rankFragment")
public RankFragment provideRankFragment() {
return this.rankFragment;
}

@Provides
@ActivityScope
public MainRankPresenter provideMainRankPresenter(RankFragment rankFragment) {
return new MainRankPresenter(new MainRankViewOps(rankFragment));
}

}


RankFragmentComponent.java

@ActivityScope
@Subcomponent(modules = {RankFragmentModule.class})
public interface RankFragmentComponent {
void inject(RankFragment rankFragment);
}


RankFragment.java

public class RankFragment extends Fragment {

@Inject
MainRankPresenter presenter;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BBBApplication.get(getContext())
.getAppComponent()
.plus(new RankFragmentModule(this))
.inject(this);
presenter.test();
}


MainRankPresenter.java

public class MainRankPresenter implements Presenter {

private MainRankViewOps viewOps;

@Inject
LoginResponseHandler loginResponseHandler;

@Inject
public MainRankPresenter(MainRankViewOps viewOps) {
this.viewOps = viewOps;
}

@Override
public void test() {
Log.d(Constants.TAG_DEBUG, "=== presenter test" + this.toString());
Log.d(Constants.TAG_DEBUG, "=== " + loginResponseHandler.toString());
this.viewOps.initViewOps();
}
}


MainRankViewOps.java

public class MainRankViewOps implements ViewOps {

RankFragment fragment;

@Inject
public MainRankViewOps(RankFragment fragment) {
this.fragment = fragment;
}

@Override
public void initViewOps() {
Log.d(Constants.TAG_DEBUG, "=== view ops" + this.toString());
Log.d(Constants.TAG_DEBUG, "=== " + fragment.toString());
}
}

Answer

Injection by Dagger 2 is not recursive. Therefore, when you call inject(this) in RankFragment only @Inject annotated fields of that fragment are being injected. Dagger 2 will not search for @Inject annotations in the injected objects.

In general, you should attempt to restrict usage of Dependency Injection frameworks to "top-level" components (Activities, Fragments, Services, etc.) which are being instantiated by Android framework for you. In objects that you instantiate yourself (like MainRankPresenter) you should use other DI techniques which do not involve external framework (e.g. dependency injection into constructor).

Comments