【问题标题】:Dagger 2 - Injecting interface in implementation class - "Attempt to invoke interface method on a null object reference"Dagger 2 - 在实现类中注入接口 - “尝试在空对象引用上调用接口方法”
【发布时间】:2015-10-12 11:52:01
【问题描述】:

当我尝试在实现类中注入接口时,总是出现空指针异常。这是我的代码:

获取:

LoginManagerImpl 类中的空指针错误:
@Override
公共字符串 getLoginResponse(字符串请求) {
return networkManager.getLoginResponse(request);
}

这里networkManager总是为空,你能看看代码吗。

下面是我的源代码:

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();
}

【问题讨论】:

    标签: android dagger-2


    【解决方案1】:

    有两种方法可以让 Dagger 将 networkManager 字段等依赖项注入 LoginManagerImpl

    1. @Inject注释其构造函数并将providesLoginManager(Context)更改为

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

      这意味着 Dagger 将提供LoginManagerImpl,并且您的@Provides 方法将LoginManager 绑定到它。

    2. 如果你想在providesLoginManager(Context) 中自己实例化LoginManagerImpl,那么也请求一个MembersInjector<LoginManagerImpl> 并用它来注入像networkManager 这样的字段:

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

    对于您的示例,我推荐选项 #1。使用 MembersInjector 对于不能让 Dagger 实例化的类非常有用,例如 Android 活动。

    【讨论】:

      【解决方案2】:

      字段注入不是自动的。您需要通过构造函数提供这些依赖项,或者您需要通过组件在类上调用成员注入。

      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();
      }
      

      【讨论】:

        【解决方案3】:

        我可以通过将 android:name="my_application_class_name" 添加到 AndroidManifest 文件中的应用程序标签来解决错误。

        【讨论】:

        • 哦!真的,它帮助了我。你为什么反对它?我投了赞成票! Android Studio 在这种情况下显示不正确的错误
        猜你喜欢
        • 2020-09-29
        • 1970-01-01
        • 1970-01-01
        • 2021-06-12
        • 2018-11-20
        • 2019-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多