Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 无法在WorkManager的Worker类中注入单例类_Android_Dependency Injection_Dagger 2_Android Workmanager - Fatal编程技术网

Android 无法在WorkManager的Worker类中注入单例类

Android 无法在WorkManager的Worker类中注入单例类,android,dependency-injection,dagger-2,android-workmanager,Android,Dependency Injection,Dagger 2,Android Workmanager,我正在研究MVVM体系结构,并使用Dagger2进行数据注入。我面临的问题是,在Activity/Fragments中,@Inject工作正常,但在WorkManager的Worker类中,@Inject在运行时出现空指针异常。我如何解决它 以下是工人阶级代码: public class MySyncManager extends Worker { @Inject DataManager dataManager; @Inject SchedulerProvid

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

以下是工人阶级代码:

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

}

在工人类中注入字段 首先,您需要将worker类注入AppComponent中:

 fun inject(syncItemWorker: SyncItemWorker)
然后在worker的doWork()中,需要调用inject:

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

您必须在要注入的模块中使用@Providers注释提供类

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

@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() {

    }
}

这个答案是从复制的,你可以检查一下

他们仍然没有对WorkManager的内部支持。它可能会出现在一个新的工件中(
dagger-android-work
),再加上对
@contributesandroid-injector
的支持

但是我们可以创造我们自己的一切来完成它。遵循下面的代码

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();
}
@Module
public abstract class AndroidWorkerInjectionModule {

@Multibinds
abstract Map<Class<? extends Worker>, AndroidInjector.Factory<? extends 
 Worker>>
workerInjectorFactories();
 }
AndroidWorkerInjectionModule.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();
}
@Module
public abstract class AndroidWorkerInjectionModule {

@Multibinds
abstract Map<Class<? extends Worker>, AndroidInjector.Factory<? extends 
 Worker>>
workerInjectorFactories();
 }
@模块
公共抽象类AndroidWorkerInjectionModule{
@多重绑定

考虑到构造函数注入,不建议使用抽象映射字段注入。这里是构造函数注入的一个很好的示例,请检查此项。基本上,您可以像这样注入:

@AssistedInject
公共预填充的数据工作者(@Assisted@NonNull上下文,@Assisted@NonNull WorkerParameters workerParams,DataManager DataManager){
超级(上下文、工作参数);
this.dataManager=dataManager;
}
@辅助工程厂
公共接口工厂扩展CustomWorkerFactory{}

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

在哪里调用
myComponent.inject(mySyncManager)
?请包含注入工作者的代码。@DavidMedenjak,我不是注入WorkManager,我只是调用上面的方法到startWorker,因为它有一些可变规则,可能会因不同的请求而有所不同。如果不注入字段,它们将为
null
,因此您必须在使用之前以某种方式注入它g it。您必须手动执行此操作,但我尝试在Worker中注入的模型已添加到AppModule中,并且在其他位置(即活动或片段)也可以正常工作。对我来说,这似乎是线程特定的问题,但我不确定。请看:。Dagger尚未支持注入Worker。是的,这就是我使用Android Injec这样做的原因tor您可以只插入android框架组件,如(服务、片段、活动),添加此行时会发生错误:@inject DataManager DataManager;@UsmanRana fun inject(syncItemWorker:syncItemWorker)您是否在应用组件中写入此行?是的,它可以工作并插入(此)在doWork方法中也是可以的。但是当我在助手类中添加@Inject时会出现编译时问题谢谢你的回答,但是当我尝试在注入后使用datamanger时,它会抛出NullPointerException。
public interface HasWorkerInjector {
AndroidInjector<Worker> workerInjector();
  }
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);
  }
}
@MapKey
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WorkerKey {
Class<? extends Worker> value();
  }