我在我的应用程序中使用 Dagger Hilt 进行 DI。每当我尝试在构造函数中注入自己的依赖项时,WorkManager 都无法初始化。但当我删除自己的依赖项时它会起作用。
我为 DI 设置了工人类别,如下所示:
UploadTripsWorker 类:
import android.content.Context
import android.util.Log
import androidx.hilt.work.HiltWorker
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.myapp.app.di.ChildWorkerFactory
import com.myapp.app.repo.UserRepositoryInterface
import com.myapp.app.repo.local.LocalDriverRepositoryInterface
import com.google.firebase.auth.FirebaseAuth
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@HiltWorker
class UploadTripsWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
private val userRepository: UserRepositoryInterface,
private val localUserRepository: LocalDriverRepositoryInterface,
private val auth: FirebaseAuth
) : CoroutineWorker(appContext, workerParams) {
@AssistedFactory
interface Factory : ChildWorkerFactory {
override fun create(appContext: Context, params: WorkerParameters): UploadTripsWorker
}
//doWork logic here
}
MyWorkerFactory 类:
import android.content.Context
import androidx.work.ListenableWorker
import androidx.work.WorkerFactory
import androidx.work.WorkerParameters
import javax.inject.Inject
import javax.inject.Singleton
import javax.inject.Provider
@Singleton
class MyWorkerFactory @Inject constructor(
private val workerFactories: Map<Class<out ListenableWorker>, @JvmSuppressWildcards Provider<ChildWorkerFactory>>
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker {
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)
}
}
ChildWorkerFactory接口:
import android.content.Context
import androidx.work.WorkerParameters
import com.myapp.app.workers.UploadTripsWorker
interface ChildWorkerFactory {
fun create(appContext: Context, params: WorkerParameters): UploadTripsWorker
}
WorkerBindingModule接口:
import com.myapp.app.workers.UploadTripsWorker
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoMap
@Module
@InstallIn(SingletonComponent::class)
interface WorkerBindingModule {
@Binds
@IntoMap
@WorkerKey(UploadTripsWorker::class)
fun bindUploadTripsWorker(factory: UploadTripsWorker.Factory): ChildWorkerFactory
}
注解类WorkerKey:
import androidx.work.ListenableWorker
import dagger.MapKey
import kotlin.reflect.KClass
@MapKey
annotation class WorkerKey(val value: KClass<out ListenableWorker>)
在AppModule内部,我提供了必要的依赖项:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideFirebaseAuth(): FirebaseAuth = FirebaseAuth.getInstance()
@Singleton
@Provides
fun provideNormalUserRepository(db: FirebaseFirestore, storage: FirebaseStorage, auth: FirebaseAuth) = UserRepository(db,storage, auth) as UserRepositoryInterface
@Singleton
@Provides
fun provideLocalDriverRepository(driverDao: DriverDao): LocalDriverRepositoryInterface {
return LocalDriverRepository(driverDao)
}
}
在清单中我使用:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
这是我的应用程序类:
@HiltAndroidApp
class MyAppApplication : Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
override fun onCreate() {
super.onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"location",
"Location Service",
NotificationManager.IMPORTANCE_LOW
)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
WorkManager.initialize(this, workManagerConfiguration)
}
}
每当我从
userRepository
的构造函数中删除 localUserRepository
、auth
和 UploadTripsWorker
时,worker 都会正常启动。
所以这没有问题:
@HiltWorker
class UploadTripsWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters
) : CoroutineWorker(appContext, workerParams) {
但是当我添加:
private val userRepository: UserRepositoryInterface,
private val localUserRepository: LocalDriverRepositoryInterface,
private val auth: FirebaseAuth
对于
UploadTripsWorker
的构造函数,它不起作用。抛出错误:
Could not instantiate com.myapp.app.workers.UploadTripsWorker (Ask Gemini)
java.lang.NoSuchMethodException: com.myapp.app.workers.UploadTripsWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
at java.lang.Class.getConstructor0(Class.java:3325)
at java.lang.Class.getDeclaredConstructor(Class.java:3063)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:94)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:243)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:144)
at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at java.lang.Thread.run(Thread.java:1012)
Could not create Worker com.myapp.app.workers.UploadTripsWorker
在我的gradle中:
//Dagger-Hilt
implementation "com.google.dagger:hilt-android:2.49"
kapt "com.google.dagger:hilt-compiler:2.44"
implementation 'androidx.hilt:hilt-common:1.2.0'
implementation 'androidx.hilt:hilt-work:1.2.0'
//Work
implementation "androidx.work:work-runtime-ktx:2.9.0"
plugins {
id 'kotlin-kapt'
id 'com.google.dagger.hilt.android'
}
我通过将
kapt("androidx.hilt:hilt-compiler:1.2.0")
添加到我的 build.gradle(Module) 文件中解决了这个问题。所以仅仅 kapt "com.google.dagger:hilt-compiler:2.44"
还不够,我们两者都需要。