-
-
Save ferrerojosh/82bd92748f315155fa6a842f4ed64c82 to your computer and use it in GitHub Desktop.
import androidx.work.Worker | |
object AndroidWorkerInjection { | |
fun inject(worker: Worker) { | |
checkNotNull(worker, { "worker" }) | |
val application = worker.applicationContext | |
if (application !is HasWorkerInjector) { | |
throw RuntimeException("${application.javaClass.canonicalName} does not implement ${HasWorkerInjector::class.java.canonicalName}") | |
} | |
val workerInjector = (application as HasWorkerInjector).workerInjector() | |
checkNotNull(workerInjector, { "${application.javaClass}.workerInjector() return null" }) | |
workerInjector.inject(worker) | |
} | |
} |
import androidx.work.Worker | |
import dagger.Module | |
import dagger.android.AndroidInjector | |
import dagger.multibindings.Multibinds | |
@Module | |
abstract class AndroidWorkerInjectionModule { | |
@Multibinds | |
abstract fun workerInjectorFactories(): Map<Class<out Worker>, AndroidInjector.Factory<out Worker>> | |
} |
import dagger.Component | |
import dagger.android.AndroidInjectionModule | |
import dagger.android.AndroidInjector | |
import javax.inject.Singleton | |
@Singleton | |
@Component(modules = [ | |
// AppModule::class, | |
// AndroidInjectionModule::class | |
// And all other related modules | |
AndroidWorkerInjectionModule::class | |
]) | |
interface AppComponent : AndroidInjector<App> { | |
@Component.Builder | |
abstract class Builder : AndroidInjector.Builder<App>() | |
} |
import androidx.work.Worker | |
import dagger.android.AndroidInjector | |
interface HasWorkerInjector { | |
fun workerInjector(): AndroidInjector<Worker> | |
} |
import androidx.work.Worker | |
import javax.inject.Inject | |
class MyWorker : Worker() { | |
override fun doWork(): WorkerResult { | |
AndroidWorkerInjection.inject(this) | |
return WorkerResult.SUCCESS | |
} | |
} |
import dagger.Subcomponent | |
import dagger.android.AndroidInjector | |
@Subcomponent | |
interface MyWorkerSubcomponent : AndroidInjector<MyWorker> { | |
@Subcomponent.Builder | |
abstract class Builder : AndroidInjector.Builder<MyWorker>() | |
} |
import androidx.work.Worker | |
import dagger.MapKey | |
import kotlin.reflect.KClass | |
@MapKey | |
@Retention(AnnotationRetention.RUNTIME) | |
@Target(AnnotationTarget.FUNCTION) | |
annotation class WorkerKey(val value: KClass<out Worker>) |
import dagger.Binds | |
import dagger.Module | |
import dagger.android.AndroidInjector | |
import dagger.multibindings.IntoMap | |
@Module(subcomponents = [ | |
MyWorkerSubcomponent::class | |
]) | |
abstract class WorkerModule { | |
@Binds | |
@IntoMap | |
@WorkerKey(MyWorker::class) | |
abstract fun bindMyWorkerFactory(builder: MyWorkerSubcomponent.Builder): AndroidInjector.Factory<out Worker> | |
} |
Would you put your application class, I would like to see how you implement "fun workerInjector(): AndroidInjector" in your application
Hello,
Thanks for your work dude. Just a question i dont see where WorkerModule class is called !!
@blackgoblin the usual:
class MyApplication: DaggerApplication(), HasWorkerInjector {
@Inject lateinit var workerInjector: DispatchingAndroidInjector<Worker>
override fun workerInjector() = workerInjector
}
@samybeng: WorkerModule
should be installed in AppComponent
workerInjector.inject(worker) this line in AndroidWorkerInjection throws 'java.lang.IllegalArgumentException: No injector factory bound for Class' exception
Hey I found this error
kotlin.UninitializedPropertyAccessException: lateinit property workerInjector has not been initialized
on this method
override fun workerInjector() = workerInjector
and workerInjector is
@Inject lateinit var workerInjector: DispatchingAndroidInjector<Worker>
@Iamsdt I'm getting the same error. Have you found a fix for it?
Hi,
I'm getting the error:
error: [Dagger/MissingBinding] [dagger.android.AndroidInjector.inject(T)] java.util.Map<java.lang.String,javax.inject.Provider<dagger.android.AndroidInjector.Factory<? extends androidx.work.Worker>>> cannot be provided without an @Provides-annotated method.
@arekolek (or anyone else) did you get this error?
Hi,
I'm getting the same error with @wellingtoncosta. The error started after I upgraded dagger 2.16 -> 2.17. Also for workmanager I have version 1.0.0-alpha09.
Hello everybody , this implementation was working beautiful, until las week. Googlers updated the library andWork()
is deprecated , now it needs Context
and WorkParameters
I have been trying to solve the issue myself, but there are plenty of thing I don't quite understand. Any idea on how to update this code?
Hi,
For the error of @wellingtoncosta and mine I found a solution. The dagger framework at DispatchingAndroidInjector takes 2 Maps at the constructor. All I needed to do was to add the extra binding:
@Module
abstract class AndroidWorkerInjectionModule {
@Multibinds
@Suppress(names = ["UNUSED"])
abstract fun workerInjectorFactories(): Map<Class<out Worker>, AndroidInjector.Factory<out Worker>>
/* New binding */
@Multibinds
@Suppress(names = ["UNUSED"])
abstract fun workerStringInjectorFactories(): Map<String, AndroidInjector.Factory<out Worker>>
}
Since the update from Work Manager and Dagger broke some things, please use this gist @luanmm made instead: https://gist.github.com/luanmm/85dd8217ed3f7384e6bab075a8ab7a61
Since you declared
worker
parameter as not null,checkNotNull
will never be executed, because Kotlin inserts its own check before that.Isn't this
application as HasWorkerInjector
cast unnecessary? I'd think Kotlin would smart-cast thisval
for you.