Skip to content

Instantly share code, notes, and snippets.

@ferrerojosh
Created May 30, 2018 06:40
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ferrerojosh/82bd92748f315155fa6a842f4ed64c82 to your computer and use it in GitHub Desktop.
Save ferrerojosh/82bd92748f315155fa6a842f4ed64c82 to your computer and use it in GitHub Desktop.
androidx workmanager injector temporary impl
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>
}
@arekolek
Copy link

fun inject(worker: Worker) {
        checkNotNull(worker, { "worker" })

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 this val for you.

@Div-e-Sepid
Copy link

Would you put your application class, I would like to see how you implement "fun workerInjector(): AndroidInjector" in your application

@samybeng
Copy link

Hello,

Thanks for your work dude. Just a question i dont see where WorkerModule class is called !!

@arekolek
Copy link

arekolek commented Jul 21, 2018

@blackgoblin the usual:

class MyApplication: DaggerApplication(), HasWorkerInjector {
    @Inject lateinit var workerInjector: DispatchingAndroidInjector<Worker>

    override fun workerInjector() = workerInjector
}

@samybeng: WorkerModule should be installed in AppComponent

@samybeng
Copy link

@arekolek 👍

@usmanrana07
Copy link

workerInjector.inject(worker) this line in AndroidWorkerInjection throws 'java.lang.IllegalArgumentException: No injector factory bound for Class' exception

@Iamsdt
Copy link

Iamsdt commented Aug 10, 2018

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>

@Abhityagi16
Copy link

@Iamsdt I'm getting the same error. Have you found a fix for it?

@wellingtoncosta
Copy link

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?

@nkontizas
Copy link

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.

@pedrovarela86
Copy link

pedrovarela86 commented Sep 26, 2018

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?

@nkontizas
Copy link

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>>
}

@ferrerojosh
Copy link
Author

Since the update from Work Manager and Dagger broke some things, please use this gist @luanmm made instead: https://gist.github.com/luanmm/85dd8217ed3f7384e6bab075a8ab7a61

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