我正在研究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();
}
答案 0 :(得分:4)
在工人类中注入字段 首先,您需要在AppComponent中注入您的worker类:
fun inject(syncItemWorker: SyncItemWorker)
然后在worker的doWork()中,你需要调用inject:
if(applicationContext is MyApp){
var daggerAppComponent= DaggerAppComponent.builder().application(applicationContext as MyApp).build()
daggerAppComponent.inject(this)
}
答案 1 :(得分:0)
您必须在模块中使用@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();
}
}
现在在您的代码中编写一个构造函数,该构造函数用于将组件注入到您的worker类中。
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复制而来的,您可以检查一下
答案 2 :(得分:0)
他们仍然没有对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中注入所有依赖项。编码愉快!
答案 3 :(得分:0)
考虑构造函数注入,不建议使用字段注入。这是构造函数注入的一个好例子,请检查此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实现