-
-
Save luanmm/85dd8217ed3f7384e6bab075a8ab7a61 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
...> | |
<application | |
...> | |
... | |
<provider | |
android:name="androidx.work.impl.WorkManagerInitializer" | |
android:authorities="<your-app-package>.workmanager-init" | |
android:enabled="false" | |
android:exported="false" | |
tools:replace="android:authorities" /> | |
</application> | |
</manifest> |
import androidx.work.Worker | |
object AndroidWorkerInjection { | |
fun inject(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 androidx.work.Configuration | |
import androidx.work.WorkManager | |
import androidx.work.Worker | |
import dagger.android.AndroidInjector | |
import dagger.android.DispatchingAndroidInjector | |
import dagger.android.support.DaggerApplication | |
import javax.inject.Inject | |
class App : DaggerApplication(), HasWorkerInjector { | |
@Inject | |
lateinit var workerInjector: DispatchingAndroidInjector<Worker> | |
override fun workerInjector(): AndroidInjector<Worker> = workerInjector | |
override fun applicationInjector(): AndroidInjector<out DaggerApplication> = | |
DaggerAppComponent.builder().create(this) | |
override fun onCreate() { | |
super.onCreate() | |
initWorkManager() | |
} | |
private fun initWorkManager() { | |
val config = Configuration.Builder() | |
.setWorkerFactory(DaggerWorkerFactory()) // Overrides default WorkerFactory | |
.build() | |
WorkManager.initialize(this, config) | |
} | |
} |
import dagger.Component | |
import dagger.android.AndroidInjector | |
import dagger.android.support.AndroidSupportInjectionModule | |
import javax.inject.Singleton | |
@Singleton | |
@Component(modules = [ | |
AndroidSupportInjectionModule::class, | |
AndroidWorkerInjectionModule::class, // Worker injection module referenced in the AppComponent | |
AppModule::class | |
]) | |
interface AppComponent : AndroidInjector<App> { | |
@Component.Builder | |
abstract class Builder : AndroidInjector.Builder<App>() | |
} |
import android.content.Context | |
import androidx.work.ListenableWorker | |
import androidx.work.Worker | |
import androidx.work.WorkerFactory | |
import androidx.work.WorkerParameters | |
class DaggerWorkerFactory : WorkerFactory() { | |
override fun createWorker( | |
appContext: Context, | |
workerClassName: String, | |
workerParameters: WorkerParameters | |
): ListenableWorker? { | |
val constructor = Class.forName(workerClassName) | |
.asSubclass(Worker::class.java) | |
.getDeclaredConstructor(Context::class.java, WorkerParameters::class.java) | |
return constructor.newInstance(appContext, workerParameters) | |
.apply { AndroidWorkerInjection.inject(this) } | |
} | |
} |
import androidx.work.Worker | |
import dagger.android.AndroidInjector | |
interface HasWorkerInjector { | |
fun workerInjector(): AndroidInjector<Worker> | |
} |
import android.content.Context | |
import androidx.work.Data | |
import androidx.work.Worker | |
import androidx.work.WorkerParameters | |
import javax.inject.Inject | |
class SampleWorker(context: Context, params: WorkerParameters) | |
: Worker(context, params) { | |
@Inject | |
lateinit var sampleRepository: SampleRepository | |
override fun doWork(): Result { | |
val myData = sampleRepository.getMyData() | |
// ... | |
} | |
companion object { | |
const val TAG = "SampleWorker" | |
} | |
} |
Hello, this is very good, but:
What about RxWorker?
This solution does not support it.
@ContributesAndroidInjector
abstract UploadWorker contributeUploadWorkerr();
solves No injector factory bound for Class<com.android.vntalk.data.service.UploadWorker>
@serhii-pokrovskyi This implementation considers Worker
as the generic worker class, but it's just the base regular worker. The more generic approach would be to use ListenableWorker
. I didn't try but swapping Worker
for ListenableWorker
in the composition classes should do make it work for RxWorker
.
@ContributesAndroidInjector
abstract UploadWorker contributeUploadWorkerr();
where i add this part to solve No injector factory bound for Class<com.android.vntalk.data.service.UploadWorker> ??
I got same error No injector factory bound for Class<com.android.vntalk.data.service.UploadWorker>
. Please help to update your configuration.
Hello, people!
Sorry about the long delay in my reply for this gist.
It was created as a first try to handle dependency injection in WorkManager. But it was implemented even before the stable release of the WorkManager. So it is not really updated and may not work in the newer library version.
I really didn't liked the way WorkManager was designed without this look for dependency injection. But now the recommended way to do it is something like this tutorial: https://proandroiddev.com/dagger-2-setup-with-workmanager-a-complete-step-by-step-guild-bb9f474bde37. It uses AssistedInject library to make things work more easily.
Personally, I think that may have a better way to instantiate workers without using AssistedInject and doing the things in a simplified way (as I tried at first). But my knowledge about the inner structure of Dagger does not allow me to design a better solution. So, for now, I am using the recommended tutorial in my personal projects aswell.
Sorry for disappointing, if it is the case who looked for someting more simplified, but currently I don't know a better way to do it. If someone knows, feel free to share or post an updated gist.
Thank you all for your considerations and for helping each other!
Best regards.
it doesn't work, app crash with log message No injector factory bound for Class<com.android.vntalk.data.service.UploadWorker>