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);
}
@usmanrana07
Copy link

usmanrana07 commented Aug 7, 2018

Hi!
I'm getting exception: java.lang.IllegalArgumentException: No injector factory bound for Class. What's missing?

@ThePredators
Copy link
Author

ThePredators commented Aug 27, 2018

@usmanrana07:
Actually nothing i have filled all what you need to declare !

Can you put the stack trace please ?

@ToniNgethe
Copy link

where is the code for @WorkerKey?

@ThePredators
Copy link
Author

@ToniNgethe

It's in WorkerModule.java !

@usmanrana07
Copy link

usmanrana07 commented Oct 15, 2018

@usmanrana07:
Actually nothing i have filled all what you need to declare !

Can you put the stack trace please ?

Here is stackTrace:

E/DefaultWorkerFactory: Could not instantiate com.fayvo.workers.LikeActionsSyncManager
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at androidx.work.DefaultWorkerFactory.createWorker(DefaultWorkerFactory.java:58)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:180)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
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:762)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at com.fayvo.di.worker.AndroidWorkerInjection.inject(AndroidWorkerInjection.java:17)

@ThePredators
Copy link
Author

@usmanrana07:
Actually nothing i have filled all what you need to declare !
Can you put the stack trace please ?

Here is stackTrace:

E/DefaultWorkerFactory: Could not instantiate com.fayvo.workers.LikeActionsSyncManager
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
at androidx.work.DefaultWorkerFactory.createWorker(DefaultWorkerFactory.java:58)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:180)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:117)
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:762)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at com.fayvo.di.worker.AndroidWorkerInjection.inject(AndroidWorkerInjection.java:17)

Send me please the hole stack trace so i can help you fastly, here is my email : predator-gist-0001@yopmail.com.

@NoumanGhaffar
Copy link

NoumanGhaffar commented Dec 18, 2018

You missed the WorkerKey class?
@ThePredators

@dseerapu
Copy link

@NoumanGhaffar

WorkerKey class is :

@MapKey
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WorkerKey {

     Class<? extends Worker> value();
}

@ThePredators
Copy link
Author

ThePredators commented Feb 21, 2019

@NoumanGhaffar
Sorry my bad !! just added it !!!

@dseerapu
Thanks for answering dude :)

@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