Не удается внедрить одноэлементные классы в рабочий класс WorkManager - PullRequest
0 голосов
/ 25 мая 2018

Я работаю над архитектурой MVVM и использую Dagger2 для внедрения данных.Проблема, с которой я сталкиваюсь, заключается в том, что в Activity / Fragments @Inject работает нормально, но в классе Worker WorkManager @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();

}

Ответы [ 4 ]

0 голосов
/ 20 марта 2019

Инжекция в полевых условиях не рекомендуется, учитывая инжекцию в конструктор.Вот хороший пример внедрения конструктора, проверьте этот блог .По сути, вы можете ввести как:

@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. Здесь - это реализация Java

0 голосов
/ 19 августа 2018

Вы должны предоставить класс, используя аннотацию @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() {

    }
}

Этот ответ скопирован из этого сообщения SO ,Вы можете проверить это

0 голосов
/ 12 февраля 2019

Они по-прежнему не имеют внутренней поддержки 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.Удачного кодирования!

0 голосов
/ 31 мая 2018

Чтобы внедрить поля в рабочий класс, сначала вам нужно внедрить ваш рабочий класс внутри AppComponent:

 fun inject(syncItemWorker: SyncItemWorker)

, а затем внутри doWork () работника, вам нужно вызвать inject:

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