Android 无法在WorkManager的Worker类中注入单例类
我正在研究MVVM体系结构,并使用Dagger2进行数据注入。我面临的问题是,在Activity/Fragments中,@Inject工作正常,但在WorkManager的Worker类中,@Inject在运行时出现空指针异常。我如何解决它 以下是工人阶级代码: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
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();
}