Dagger 2 - Injecting interface in implementation class - "Attempt to invoke interface method on a null object reference"
Solution 1
There are two ways for you to let Dagger inject dependencies like the networkManager
field into LoginManagerImpl
.
Annotate its constructor with
@Inject
and changeprovidesLoginManager(Context)
to@Provides @Singleton LoginManager providesLoginManager(LoginManagerImpl manager) { return manager; }
That will mean Dagger will provide the
LoginManagerImpl
, and your@Provides
method bindsLoginManager
to that.If you want to instantiate
LoginManagerImpl
yourself inprovidesLoginManager(Context)
, then also request aMembersInjector<LoginManagerImpl>
and use it to inject fields likenetworkManager
:@Provides @Singleton LoginManager providesLoginManager(Context context, MembersInjector<LoginManagerImpl> membersInjector) { LoginManagerImpl manager = new LoginManagerImpl(context); membersInjector.injectMembers(manager); return manager; }
For your example, I'd recommend option #1. Using MembersInjector
is really useful for classes that you cannot let Dagger instantiate, like Android Activities.
Solution 2
Field injection is not automatic. You need to provide those dependencies through the constructor, or you need to invoke member injection on the class via the component.
public class LoginActivity extends Activity {
@Inject
NetworkManager networkManager;
@Inject
LoginManager loginManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getApplicationComponent().inject(this);
loginManager.getLoginResponse("valid Login Request");
}
}
public interface NetworkManager {
String getLoginResponse(String request);
String getUserDetailResponse(String request);
String getABCResponse(String request);
}
public interface LoginManager {
String getLoginResponse(String request);
}
@Singleton
public class LoginManagerImpl implements LoginManager {
private final NetworkManager networkManager;
@Inject
public LoginManagerImpl(NetworkManager networkManager) {
this.networkManager = networkManager;
}
@Override
public String getLoginResponse(String request) {
return networkManager.getLoginResponse(request);
}
}
@Singleton
public class NetworkManagerImpl implements NetworkManager {
@Inject
NetworkManagerImpl(){
}
@Override
public String getLoginResponse(String request) {
return "valid login response fetched from server";
}
@Override
public String getUserDetailResponse(String request) {
return "valid user deails";
}
@Override
public String getABCResponse(String request) {
return "valid ABC request response";
}
}
@Module
public class AppModule {
DaggerApplication application;
public AppModule(DaggerApplication application) {
this.application = application;
}
@Provides
DaggerApplication provideDaggerApplication() {
return application;
}
@Provides
Context provideApplicationContext() {
return application.getApplicationContext();
}
}
@Module
public abstract class ManagerModule {
@Binds
abstract LoginManager loginManager(LoginManagerImpl impl);
@Binds
abstract LoyaltyCardManager loyaltyCardManager(LoyaltyCardManagerImpl impl);
@Binds
abstract NetworkManager networkManager(NetworkManagerImpl impl);
}
@Singleton
@Component(
modules = {
com.acme.di.component.AppModule.class,
com.acme.di.component.ManagerModule.class
})
public interface ApplicationComponent {
void inject (LoginActivity activity);
NetworkManager getNetworkManager();
LoginManager getLoginManager();
}
Piyush
Updated on June 21, 2022Comments
-
Piyush about 2 years
I am always getting null pointer exception when I try to inject interface in implementation class. here is my code:
Getting:
Nullpointer error in LoginManagerImpl class at line:
@Override
public String getLoginResponse(String request) {
return networkManager.getLoginResponse(request);
}here networkManager is always null, can you please look into the code.
Below is my source code:
public class LoginActivity extends Activity { @Inject NetworkManager networkManager; @Inject LoginManager loginManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getApplicationComponent().inject(this); loginManager.getLoginResponse("valid Login Request"); } } public interface NetworkManager { String getLoginResponse(String request); String getUserDetailResponse(String request); String getABCResponse(String request); } public interface LoginManager { String getLoginResponse(String request); } public class LoginManagerImpl implements LoginManager { @Inject NetworkManager networkManager; public LoginManagerImpl(Context context) { } @Override public String getLoginResponse(String request) { return networkManager.getLoginResponse(request); } } public class NetworkManagerImpl implements NetworkManager { public NetworkManagerImpl(Context context) { } @Override public String getLoginResponse(String request) { return "valid login response fetched from server"; } @Override public String getUserDetailResponse(String request) { return "valid user deails"; } @Override public String getABCResponse(String request) { return "valid ABC request response"; } } @Module public class AppModule { DaggerApplication application; public AppModule(DaggerApplication application) { this.application = application; } @Provides @Singleton DaggerApplication provideDaggerApplication() { return application; } @Provides @Singleton public Context provideApplicationContext() { return application.getApplicationContext(); } @Provides @Singleton public LoginManager providesLoginManager(Context context) { return new LoginManagerImpl(); } @Provides @Singleton public LoyaltyCardManager providesLoyaltyCardManager(Context context) { return new LoyaltyCardManagerImpl(context); } @Provides @Singleton public NetworkManager providesNetworkManager(Context context) { return new NetworkManagerImpl(context); } } @Singleton @Component( modules = { com.dagger.component.AppModule.class }) public interface ApplicationComponent { void inject (LoginActivity activity); NetworkManager getNetworkManager(); LoginManager getLoginManager(); }
-
Dyno Cris almost 4 yearsOh! Really, it helped me. Why you downvote it? I upvoted! Android Studio shows uncorrect error in this case