我想在工作管理器中注入存储库和其他存储库。由于工作管理器是和Android组件,我不能只是在构造中注入东西,但我必须创建一个工厂类。所以我在 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"
然后我有工作管理器模块,我在其中绑定了我的工人类工厂
@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
}
以及我想在其中构建 DagggerComponent 的应用程序类
val factory: AppWorkerFactory = DaggerWorkManagerComponent.create().factory()
WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(factory).build())
所以我的工作管理器类就像
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 {
嗯....似乎Dagger2注入工作管理器尚无法完成。Github中有一个悬而未决的问题。任何知道的人请告知!!
解决方案是下面的代码(每个部分都是我的项目的单独文件(
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的应用组件应该像
@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
工作器模块应该是和接口
@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" />