【问题标题】:How to Inject IntentService in Dagger2.11如何在 Dagger2.11 中注入 IntentService
【发布时间】:2017-12-27 11:29:41
【问题描述】:

我在我的项目中使用 Dagger2 发布的库。我已将 AppComponent 定义为:

  @Singleton
@Component(modules = {
        AndroidInjectionModule.class, AppModule.class, ActivityBuilder.class })
public interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

    void inject(TraderApplication traderApplication);
}

然后ActivityBuilder会定义具体的activity和相关模块为:

 @Module
public abstract class ActivityBuilder {

    @ContributesAndroidInjector(modules = SplashActivityModule.class)
    abstract SplashActivity bindSplashActivity();
}

并且 SplashActivityModule 提供的依赖项为:

  @Module
public class SplashActivityModule {

    @Provides
    SplashViewModel provideLoginViewModel(TraderRepository traderRepository, Application application, SharedPreferenceUtils sharedPreferenceUtils, AppExecutors appExecutors) {
        return new SplashViewModel(traderRepository, application, sharedPreferenceUtils, appExecutors);
    }
}

现在,我正在从 SplashActivity 调用 IntentService(以加载一些设置数据),但在该 IntentService 内部我无法 @Inject SharePreference、AppExecuters 等的依赖项。AppModule 定义为:

@Module
public class AppModule {
@Provides
    @Singleton
    TraderRepository provideIssueRepository(TraderListRepositoryImpl repository) {
        return repository;
    }

 @Provides
    @Singleton
    SharedPreferences providesSharedPreferences(Application application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }
}

**更新_1: 在 SetupDataService 内部,我尝试像在 onCreate 内部一样注入:

  public class SetupDataService extends IntentService implements HasServiceInjector {

    @Inject
        SharedPreferenceUtils mSharedPreferenceUtils;

         @Inject
            AndroidInjector<Service> fragmentDispatchingAndroidInjector;

            @Override
            public AndroidInjector<Service> serviceInjector() {
                return fragmentDispatchingAndroidInjector;
            }

            @Override
            public void onCreate() {
                AndroidInjection.inject(this);
                super.onCreate();
            }
    @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            assert intent != null;

    //**update_2 :
    if(mSharedPreferenceUtils != null) //still null here after using @binds
    {
    }
 }
}

它不允许我们注入,即使我尝试在应用程序类中实现 HasServiceInjector。它抛出: '不能在没有@Provide 或@Produce 的情况下注入服务'。

**Update_1 到此结束..

如何使用 Dagger2.11 版本注入 Intent 服务。我尝试定义:

 void inject(IntentService intentService);

在 AppComponent 内部,但在注入依赖项时我仍然得到 NULL 值。

**Update_2:

我尝试在 Service 类中注入的 SharedPreferenceUtils 类在 onHandleIntent 中返回 null :

@Singleton
public class SharedPreferenceUtils {

    //region Private Fields
    private SharedPreferences mSharedPreferences;
    private final String TAG = SharedPreferenceUtils.class.getSimpleName();
    private final Method APPLY_METHOD = findApplyMethod();
    //endregion

    @Inject
    public SharedPreferenceUtils(SharedPreferences mSharedPreferences) {
        this.mSharedPreferences = mSharedPreferences;
    }
}

**Update_2 到此结束..

这里有任何帮助..

谢谢。

【问题讨论】:

标签: android dagger-2 dagger


【解决方案1】:

即使我尝试在应用程序类中实现 HasServiceInjector。它抛出:'Cannot injection Service without @Provide or @Produce'。

正确的做法是这样做:让您的应用程序实现 HasServiceInjector。 AndroidInjection.inject() 的重点是您正在获取 Android 创建的对象,因此无法自然访问您的 DI 图,并让它自动将 Application 转换为 HasServiceInjector 以便它可以尝试注入服务。查看AndroidInjection中的实现(添加了cmets):

public static void inject(Service service) {
  checkNotNull(service, "service");
  Application application = service.getApplication();
  // Don't even bother checking the service itself, just check the Application.
  if (!(application instanceof HasServiceInjector)) {
    throw new RuntimeException(
        String.format(
            "%s does not implement %s",
            application.getClass().getCanonicalName(),
            HasServiceInjector.class.getCanonicalName()));
  }

  // As long as serviceInjector() returns non-null...
  AndroidInjector<Service> serviceInjector =
      ((HasServiceInjector) application).serviceInjector();
  checkNotNull(serviceInjector, "%s.serviceInjector() returned null",
      application.getClass());

  // ...ask it to inject your service.
  serviceInjector.inject(service);
}

听起来你真正的问题是你试图注入服务,这是不允许的:你可以注入 SetupDataService,但不存在服务或 IntentService 的绑定。您可以自己将它们添加到您在 @ContributesAndroidInjector 绑定上为您的 SetupDataService 安装的模块中:

@ContributesAndroidInjector(modules = SetupDataServiceModule.class)
SetupDataService bindSetupDataService();

@Module interface SetupDataServiceModule {
  @Binds Service bindService(SetupDataService service);
  @Binds IntentService bindIntentService(SetupDataService service);
}

...但除非您正在编写适用于多个服务的可重用代码,或者除非您有构建图约束并试图避免在其他代码段中直接引用您的 SetupDataService,否则您可能只想坚持改为注入 SetupDataService。

请参阅this answer from yesterday 了解更多背景信息,包括您为什么要在此处为​​服务而不是片段执行此操作。

【讨论】:

  • 我尝试在 AcitivityBuilder 中独立使用 @ContributesAndroidInjector,甚至尝试链接到 SplashActivity -> 贡献注入器。但不幸的是,两者都没有奏效。在注入 SharedPreferenceUtils 依赖项时,我仍然得到空对象。我错过了什么 ?谢谢。
  • @prdp89 不可能说你是否错过了什么,因为你没有向我们展示你在哪里或如何注入 SharedPreferenceUtils。没有可重现的例子,我不得不根据你的错误信息来猜测。
  • 今天刚刚通过关注 (stackoverflow.com/questions/45341072/…) 解决了这个问题。您如何看待这种用于服务模块的通用方法?
  • @prdp89 该答案向您展示了 manual 的操作方式;使用DaggerIntentService@ContributesAndroidInjector,您可以自动化一些样板文件。特别是它显示的ServiceModule 非常好,但是使用@BindsInstance 可以让Dagger 生成更优化的代码。如果你已经让它工作了,你可能想继续前进,在你更熟悉 Dagger 和 dagger.android 之后再重新访问它。
猜你喜欢
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多