Dagger 2 - Injection interface in the implementation class - "Attempting to invoke an interface method to reference a null object"

I always get a null pointer exception when I try to inject an interface into an implementation class. here is my code:

Receiving:

Nullpointer error in LoginManagerImpl class in line:
@Override
public String getLoginResponse (query string) {
return networkManager.getLoginResponse (request);
}

here networkManager is always null , can you 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(); } 
+5
source share
3 answers

There are two ways to allow daggers to networkManager dependencies, such as the networkManager field, in LoginManagerImpl .

  • Annotate your constructor with @Inject and change the providesLoginManager(Context) to

     @Provides @Singleton LoginManager providesLoginManager(LoginManagerImpl manager) { return manager; } 

    This will mean that the dagger will provide LoginManagerImpl , and your @Provides method will associate LoginManager with this.

  • If you want to create an instance of LoginManagerImpl yourself in providesLoginManager(Context) , then query MembersInjector<LoginManagerImpl> and use it to enter fields of type networkManager :

     @Provides @Singleton LoginManager providesLoginManager(Context context, MembersInjector<LoginManagerImpl> membersInjector) { LoginManagerImpl manager = new LoginManagerImpl(context); membersInjector.injectMembers(manager); return manager; } 

In your example, I would recommend option # 1. Using MembersInjector really useful for classes that you cannot allow an instance of Dagger, such as Android Activities.

+5
source

Field injection is not automatic. You must provide these dependencies through the constructor, or you need to call the implementation of the member in the class through 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(); } 
+1
source

I managed to resolve this error by adding android:name="my_application_class_name" to the application tag in the AndroidManifest file.

0
source

Source: https://habr.com/ru/post/1233519/


All Articles