【问题标题】:Dagger injection to Workamanager AssistedInject_AppAssistedInjectModule匕首注入 Workamanager AssistedInject_AppAssistedInjectModule
【发布时间】:2020-02-10 17:09:42
【问题描述】:

我想在 workmanager 中注入存储库和其他内容。由于 workmanager 和 Android 组件我不能只在 construcotr 中注入东西,但我必须创建一个工厂类。所以我在 Medium 上找到了一个例子,然后我就跟着做了。我有依赖项

// 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"

然后我有绑定我的 WorkerClass 工厂的 WorkManager 模块

@Module
interface WorkManagerModule {

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

}

工作管理器组件


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

还有工厂

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
}

以及我要构建 DaggerComponent 的 Application 类

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

所以我的 WorkManager 类是这样的

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

在构建项目时出现多个错误。但前两个错误似乎是真正的问题。我无法理解它可能出了什么问题。他们来了。

...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 {

【问题讨论】:

  • 您可能只是缺少类导入。
  • 从 messageRepository 中删除注释 @Assisted。这不是必需的,你使用 Assisted 来处理 Dagger graph 无法提供的依赖项。

标签: android dagger-2 android-workmanager assisted-inject


【解决方案1】:

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

【讨论】:

  • 不...完全有可能,我已经做到了。我将在几分钟后粘贴一个示例
【解决方案2】:

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

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

}

还有Application类

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

    }

最后你应该在应用标签的清单中声明workmanager

<provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="${applicationId}.workmanager-init"
            android:exported="false"
            tools:node="remove" />

【讨论】:

    猜你喜欢
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多