0

I want to inject repositories and others in the workmanager. Since workmanager is and Android Component i cannot just inject stuff in the construcotr but i have to make a Factory class. So i found an example on Medium and i followed it. I have the dependencies

// Dagger 2
    def dagger_version = '2.24'
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android-support:$dagger_version"
    annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"

    // Assisted Injection
    def dagger_assist_version = '0.3.3'
    implementation "com.squareup.inject:assisted-inject-annotations-dagger2:$dagger_assist_version"
    kapt "com.squareup.inject:assisted-inject-processor-dagger2:$dagger_assist_version"

Then i have the WorkManager Module where i bind my WorkerClass Factory

@Module
interface WorkManagerModule {

    @Binds
    @IntoMap
    @WorkManagerKey(FileSplitter::class)
    fun bindImageSplitterWorker(factory: FileSplitter.Factory): ChildWorkerFactory

}

WorkManagerComponent


@Component(modules = [AppAssistedInjectModule::class, WorkManagerModule::class])
interface WorkManagerComponent {
    fun factory(): AppWorkerFactory
}

And the Factories

class AppWorkerFactory @Inject constructor(
    private val workerFactories: Map<Class<out CoroutineWorker>,
            @JvmSuppressWildcards Provider<ChildWorkerFactory>>
) : WorkerFactory() {
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): CoroutineWorker? {
        val foundEntry =
            workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) }
        val factoryProvider = foundEntry?.value
            ?: throw IllegalArgumentException("unknown worker class name: $workerClassName")
        return factoryProvider.get().create(appContext, workerParameters)
    }
}


interface ChildWorkerFactory {
    fun create(appContext: Context, params: WorkerParameters): CoroutineWorker
}

And the Application class where i want to build the DaggerComponent

        val factory: AppWorkerFactory = DaggerWorkManagerComponent.create().factory()
        WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(factory).build())

So my WorkManager class is like

class FileSplitter @AssistedInject constructor(
    @Assisted private val appContext: Context,
    @Assisted private val params: WorkerParameters,
    @Assisted private val messagesRepository: MessagesRepository
) : CoroutineWorker(appContext, params) {

    override val coroutineContext = Dispatchers.IO

    override suspend fun doWork(): Result = coroutineScope {
        ... CODE...
        Result.success()
    }

    @AssistedInject.Factory
    interface Factory : ChildWorkerFactory
    companion object {
        private const val TAG = "ImageSplitterWorker"
    }
}

On build Project i get multiple errors. But the first two errors seems to be the real problem. I cannot understand what it maybe going wrong. Here they are.

...di/modules/AppAssistedInjectModule.java:7: error: cannot find symbol
@dagger.Module(includes = {AssistedInject_AppAssistedInjectModule.class})
                           ^
  symbol: class AssistedInject_AppAssistedInjectModule

..di//modules/AppAssistedInjectModule.java:8: error: [ComponentProcessor:MiscError] dagger.internal.codegen.ComponentProcessor was unable to process this class because not all of its dependencies could be resolved. Check for compilation errors or a circular dependency with generated code.
public abstract class AppAssistedInjectModule {
4

2 回答 2

0

嗯....似乎 Dagger2 Injection to workmanager 还不能完成。Github 中有一个未解决的问题。有知道的请告知!!

于 2020-02-11T15:06:12.097 回答
0

解决方案是下面的代码(每个部分都是我项目的单独文件)

Gradle 导入

// Dagger 2
    def dagger_version = '2.27'
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android-support:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"

    // Assisted Injection
    def dagger_assist_version = '0.5.2'
    compileOnly "com.squareup.inject:assisted-inject-annotations-dagger2:$dagger_assist_version"
    kapt "com.squareup.inject:assisted-inject-processor-dagger2:$dagger_assist_version"

工人阶级


class FileSplitterWorker @AssistedInject constructor(
    @Assisted private val appContext: Context,
    @Assisted private val params: WorkerParameters,
    private val messagesRepository: MessagesRepository
) : CoroutineWorker(appContext, params) {

    override suspend fun doWork(): Result {

        // Do Work with messageRepository

        return Result.success()
    }

    @AssistedInject.Factory
    interface Factory : ChildWorkerFactory
}

创建这个接口

interface ChildWorkerFactory {
    fun create(appContext: Context, params: WorkerParameters): CoroutineWorker
}

和工人的工厂班

class AppWorkerFactory @Inject constructor(
    private val workerFactories: Map<Class<out CoroutineWorker>, @JvmSuppressWildcards Provider<ChildWorkerFactory>>
) : WorkerFactory() {
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): CoroutineWorker? {
        val foundEntry =
            workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) }
        val factoryProvider = foundEntry?.value
            ?: throw IllegalArgumentException("unknown worker class name: $workerClassName")
        return factoryProvider.get().create(appContext, workerParameters)
    }
}

Dagger 的 AppComponent 应该像

@Singleton
@Component(
    modules = [
AndroidInjectionModule::class,
        AndroidSupportInjectionModule::class,
        AppAssistedInjectModule::class,
        WorkManagerModule::class,
        etc etc...
    ]
)
interface AppComponent {
    fun inject(application: MyApplication)

    fun workerFactory(): AppWorkerFactory

    @Component.Factory
    interface Factory {
        fun withContext(@BindsInstance application: MyApplication): AppComponent
    }
}


@Module(includes = [AssistedInject_AppAssistedInjectModule::class])
@AssistedModule
interface AppAssistedInjectModule

WorkerModule 应该是和接口


@Module(includes = [RepositoryModule::class, etc etc])
interface WorkManagerModule {

    @Binds
    @IntoMap
    @WorkManagerKey(FileSplitterWorker::class)
    fun bindFileSplitterWorker(factory: FileSplitterWorker.Factory): ChildWorkerFactory

}

和应用程序类

override fun onCreate() {
        super.onCreate()
        instance = this


        val daggerAppComponent = DaggerAppComponent.factory().withContext(this)
        daggerAppComponent.inject(this)
        val factory: AppWorkerFactory = daggerAppComponent.workerFactory()
        WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(factory).build())

}

companion object {
        private lateinit var instance: MyApplication

    }

最后,您应该在应用程序标签中将工作管理器声明为清单

<provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="${applicationId}.workmanager-init"
            android:exported="false"
            tools:node="remove" />
于 2020-04-30T18:58:12.960 回答