Skip to content

Instantly share code, notes, and snippets.

@ThePredators
Last active December 30, 2021 03:27
Show Gist options
  • Save ThePredators/1702e79c5d3860f415c542da446420eb to your computer and use it in GitHub Desktop.
Save ThePredators/1702e79c5d3860f415c542da446420eb to your computer and use it in GitHub Desktop.
[Dagger] integration with workers (For Java People)

Android Dagger (Java)

This files have been created in 2017 when Google introduced for the first time Android Jetpack Workers.

This implementation show how to use Dagger with Workers

The above usage might been deprecated since now we have Hilt

public class AndroidWorkerInjection {
public static void inject(Worker worker) {
checkNotNull(worker, "worker");
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);
}
}
@Module
public abstract class AndroidWorkerInjectionModule {
@Multibinds
abstract Map<Class<? extends Worker>, AndroidInjector.Factory<? extends Worker>>
workerInjectorFactories();
}
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
AndroidWorkerInjectionModule.class,
WorkerModule.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(MyApplication application);
AppComponent build();
}
void inject(MyApplication app);
}
public interface HasWorkerInjector {
AndroidInjector<Worker> workerInjector();
}
public class MyApplication extends MultiDexApplication implements HasWorkerInjector {
@Inject DispatchingAndroidInjector<Worker> workerDispatchingAndroidInjector;
public AppComponent appComponent;
@Override
public void onCreate() {
super.onCreate();
MultiDex.install(this);
appComponent = DaggerAppComponent
.builder()
.application(this)
.build();
appComponent.inject(this);
//Call the Profile Worker
OneTimeWorkRequest refreshProfile =
new OneTimeWorkRequest.Builder(ProfileWorker.class)
.addTag(ConstantsUtils.TAG_OUTPUT)
.build();
WorkManager.getInstance().enqueue(refreshProfile);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
@Override
public AndroidInjector<Worker> workerInjector() {
return workerDispatchingAndroidInjector;
}
}
public class ProfileWorker extends Worker {
@Inject
SomeClass clazz;
@NonNull
@Override
public WorkerResult doWork() {
AndroidWorkerInjection.inject(this);
// Do work here :
return WorkerResult.SUCCESS;
}
}
@Subcomponent
public interface ProfileWorkerModule extends AndroidInjector<ProfileWorker> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<ProfileWorker>{}
}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface WorkerKey {
Class<? extends Worker> value();
}
@Module(subcomponents = {
ProfileWorkerModule.class,
UploadWorkerModule.class
})
public abstract class WorkerModule {
@Binds
@IntoMap
@WorkerKey(ProfileWorker.class)
abstract AndroidInjector.Factory<? extends Worker> bindProfileWorkerFactory(ProfileWorkerModule.Builder profileWorker);
}
@carvalho2707
Copy link

Can you update this guide with testing configuration?

@rickmune
Copy link

@ThePredators
Thanks for the above. Mighty help.

Not sure what I am missing but I get the below stacktrace

2019-12-17 14:08:15.007 28634-28652/com.exsolv.eform E/WM-WorkerWrapper: Work [ id=dca5c889-881e-498d-81ff-f90d8e2af3f9, tags={ com.exsolv.eform.data.remote.services.UploadWorker } ] failed because it threw an exception/error
java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: No injector factory bound for Class<com.exsolv.eform.data.remote.services.UploadWorker>
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:284)
at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<com.exsolv.eform.data.remote.services.UploadWorker>
at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:136)
at com.exsolv.eform.factory.AndroidWorkerInjection.inject(AndroidWorkerInjection.java:26)
at com.exsolv.eform.data.remote.services.UploadWorker.doWork(UploadWorker.java:43)
at androidx.work.Worker$1.run(Worker.java:85)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
at java.lang.Thread.run(Thread.java:761) 

@ThePredators
Copy link
Author

@rickmune :

can u show how u used class UploadWorker ? Ty.

@ThePredators
Copy link
Author

ThePredators commented Jan 5, 2021

for people that use Kotlin i advice to stop using dagger and go for this light weight plugin
--> Koin

To Know how to use Koin i made a simple tutorial for every purpose in here :
--> Koin Tutos

@cbeyls
Copy link

cbeyls commented May 21, 2021

I guess this is now deprecated and you should use Hilt Worker Injection

@ThePredators
Copy link
Author

ThePredators commented May 21, 2021

@cbeyls : you can still use this. Dagger is a Java library that has been used on Android. Now they made a much simpler way to do DI using Hilt.

But personally I like Koin much more!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment