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();
}
We can simply use @Inject at constructor! TL DR; If you have provide methods which just call constructor of implementation classes to inject interfaces, use @Binds annotation instead to get rid of boilerplate code in your dagger module.
The term dependency injection context is typically used to describe the set of objects which can be injected. In Dagger 2, classes annotated with @Module are responsible for providing objects which can be injected. Such classes can define methods annotated with @Provides .
There are two ways for you to let Dagger inject dependencies like the networkManager
field into LoginManagerImpl
.
Annotate its constructor with @Inject
and change providesLoginManager(Context)
to
@Provides @Singleton
LoginManager providesLoginManager(LoginManagerImpl manager) {
return manager;
}
That will mean Dagger will provide the LoginManagerImpl
, and your @Provides
method binds LoginManager
to that.
If you want to instantiate LoginManagerImpl
yourself in providesLoginManager(Context)
, then also request a MembersInjector<LoginManagerImpl>
and use it to inject fields like networkManager
:
@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.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With