【问题标题】:Cannot inject singleton classes in Worker class of WorkManager无法在 WorkManager 的 Worker 类中注入单例类
【发布时间】:2018-05-25 11:37:38
【问题描述】:

我正在研究 MVVM 架构,并且正在使用 Dagger2 进行数据注入。我面临的问题是,在 Activity/Fragments 中,@Inject 工作正常,但在 WorkManager 的 Worker 类中,@Inject 在运行时给出空指针异常。我该如何解决?

以下是Worker类代码:

public class MySyncManager extends Worker {

    @Inject
    DataManager dataManager;

    @Inject
    SchedulerProvider schedulerProvider;

    @NonNull
    @Override
    public WorkerResult doWork() {

        CommonUtils.Log("usm_work_manager_1", "Work is Started.");
         if(dataManager==null) 
        CommonUtils.Log("usm_work_manager", "Injector is NULL");

    }
    }

方法:

    private void startTestSyncRequest() {
        Constraints myConstraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();
        OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(MySyncManager.class)
                .setConstraints(myConstraints)
                .setInitialDelay(1, TimeUnit.SECONDS)  // wait for n seconds before starting service
                .build();

        WorkManager.getInstance()
                .beginUniqueWork(Tags.TEST_WORK_NAME, ExistingWorkPolicy.REPLACE, workRequest)
                .enqueue();

}

【问题讨论】:

  • 你在哪里打电话给myComponent.inject(mySyncManager)?请包含您注入工作人员的代码。
  • @DavidMedenjak,我没有注入 WorkManager,我只是调用上面的方法来 startWorker,因为它有一些可变规则,可能会因不同的请求而异。
  • 如果你不注入字段,它们将是null,所以你必须在使用它之前以某种方式注入它。您必须手动执行此操作
  • 但是我试图在 Worker 中注入的模型被添加到 AppModule 中,它在其他地方也可以正常工作,即活动或片段。对我来说,这似乎是线程特定的问题,但我不确定。

标签: android dependency-injection dagger-2 android-workmanager


【解决方案1】:

在工人类中注入字段 首先你需要在 AppComponent 中注入你的工作类:

 fun inject(syncItemWorker: SyncItemWorker)

那么在worker的doWork()里面,你需要调用inject:

 if(applicationContext is MyApp){
        var daggerAppComponent= DaggerAppComponent.builder().application(applicationContext as MyApp).build()
        daggerAppComponent.inject(this)
    }

【讨论】:

  • 见这个:prntscr.com/jp7ru6。 Dagger 尚不支持在 Worker 中注入。
  • 是的,这就是我这样做的原因,使用 Android Injector 你可以只注入 android 框架组件,如(服务、片段、活动),
  • 添加此行时发生错误:@Inject DataManager dataManager;
  • @UsmanRana fun inject(syncItemWorker: SyncItemWorker) 你在你的 AppComponent 里写这行吗?
  • 是的,它可以工作,并且在 doWork 方法中注入(this)也可以。但是当我用我的助手类添加@Inject 时会出现编译时问题
【解决方案2】:

你必须在要注入的模块中使用@Provides注解来提供类。

首先创建一个包含提供类的模块的组件。

@Component(modules = {Module.class})
public interface Component1{

    void inject(MySyncManager mySyncManager);
}

模块类

@Module
public class Module{

    @Provides
    public DataManager provideDataManager(){
        return new DataManager();
    }

    @Provides
    public SchedulerProvider provideSchedulerProvider(){
        return new SchedulerProvider();
    }

}

现在在您的代码中编写一个构造函数,用于将组件注入您的工作类。

public class MySyncManager extends  Worker {

    @Inject
    DataManager dataManager;

    @Inject
    SchedulerProvider schedulerProvider;

    public MySyncManager(){
        DaggerComponent1.builder().build().inject();
    }

    @NonNull
    @Override
    public Result doWork() {

        sync();
        return Result.SUCCESS;
    }

    private void sync() {

    }
}

这个答案是从this SO post复制过来的,你可以查一下

【讨论】:

  • 感谢您的回答,但是当我在注入后尝试使用 datamanger 时会抛出 NullPointerException。
【解决方案3】:

他们仍然没有对 WorkManager 的内部支持。它可能会出现在新的工件 (dagger-android-work) 中,并支持 @ContributesAndroidInjector

但我们可以创建自己的一切来完成它。按照下面的代码。

AppComponent.java

    @Singleton
    @Component(modules = {//rest of your modules,
    AndroidWorkerInjectionModule.class,
    WorkerModule.class})
   public interface AppComponent {

@Component.Builder
interface Builder {

    @BindsInstance
    Builder application(Application application);

    AppComponent build();
}

void inject(App npp);

DataManager getDataManager();
}

AndroidWorkerInjectionModule.java

@Module
public abstract class AndroidWorkerInjectionModule {

@Multibinds
abstract Map<Class<? extends Worker>, AndroidInjector.Factory<? extends 
 Worker>>
workerInjectorFactories();
 }

WorkerModule.class

@Module(subcomponents = {
    WorkerComponent.class
     })
  public abstract class WorkerModule {
  @Binds
  @IntoMap
  @WorkerKey(CustomWorkManager.class)
  abstract AndroidInjector.Factory<? extends Worker> 
  bindProfileWorkerFactory(WorkerComponent.Builder profileWorker);
    }

WorkerComponent.class

@Subcomponent
public interface WorkerComponent extends AndroidInjector<CustomWorkManager> {
   //Here, CustomWorkManager is the class that extends Worker of WorkManager.You write your own class
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<CustomWorkManager>{}

}

HasWorkerInjector.class

public interface HasWorkerInjector {
AndroidInjector<Worker> workerInjector();
  }

AndroidWorkerInjection.class

public class AndroidWorkerInjection {

public static void inject(Worker worker) {
    //TODO : Check not null

    Object application = worker.getApplicationContext();

    if (!(application instanceof HasWorkerInjector)) {
        throw new RuntimeException(
                String.format(
                        "%s does not implement %s",
                        application.getClass().getCanonicalName(),
                        HasWorkerInjector.class.getCanonicalName()));
    }

    AndroidInjector<Worker> workerInjector =
            ((HasWorkerInjector) application).workerInjector();
    checkNotNull(workerInjector, "%s.workerInjector() returned null", 
   application.getClass());
    workerInjector.inject(worker);
  }
}

WorkerKey.class

@MapKey
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WorkerKey {
Class<? extends Worker> value();
  }

现在您可以在 CustomWorkManager 中注入所有依赖项。快乐编码!

【讨论】:

    【解决方案4】:

    考虑到构造函数注入,不建议使用字段注入。这是构造函数注入的一个很好的例子,检查这个blog。基本上你可以像这样注入:

    @AssistedInject
    public PrePopulateDataWorker(@Assisted @NonNull Context context, @Assisted @NonNull WorkerParameters workerParams, DataManager dataManager) {
        super(context, workerParams);
        this.dataManager = dataManager;
    }
    
    @AssistedInject.Factory
    public interface Factory extends CustomWorkerFactory {}
    

    这里注入了DataManger 的实例。 Here是Java实现

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多