使用 Hilt 注入 CoroutineWorker

Min*_*aac 6 android coroutine kotlin dagger-hilt

我正在尝试使用 dagger hilt 注入协同工作程序,我已按照文档中的所有说明进行操作

https://developer.android.com/training/dependency-injection/hilt-jetpack 用于“工人”而不是“协程工人”..

但它给出了一个错误:

java.lang.NoSuchMethodError: No interface method getBackgroundExecutor()Ljava/util/concurrent/Executor

..在stackoverflow上发布了同样的问题,但答案不适合我的情况

无法使用 Hilt 注入 workmanager 构造函数

这是代码和错误

如果有人可以提供帮助,我将不胜感激……这是我的代码

package com.example.moviemania.work

import android.content.Context
import androidx.hilt.Assisted
import androidx.hilt.work.WorkerInject
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.example.moviemania.repository.MainRepository
import retrofit2.HttpException

class RefreshDataWorker @WorkerInject constructor (
    @Assisted appContext: Context,
    @Assisted params: WorkerParameters,
    val mainRepository: MainRepository
    ) : CoroutineWorker(appContext,params) {

    companion object {
        const val WORK_NAME = "com.example.moviemania.work.RefreshDataWorker"
    }

    override suspend fun doWork(): Result {
        try {
            mainRepository.refreshMovies()
        }catch (e: HttpException){
            return Result.retry()
        }
        return Result.success()
    }
}

@HiltAndroidApp
class MoviesApp : Application(), Configuration.Provider {
    @Inject lateinit var workerFactory: HiltWorkerFactory

    private val applicationScope = CoroutineScope(Dispatchers.Default)
    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .setMinimumLoggingLevel(android.util.Log.DEBUG)
            .build()


    override fun onCreate() {
        super.onCreate()
        delayedInit()
    }

    private fun delayedInit() {
        applicationScope.launch {
            setupRecurringWork()
        }
    }
    private fun setupRecurringWork(){
        val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1,TimeUnit.DAYS).build()
        WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork(
            RefreshDataWorker.WORK_NAME,
            ExistingPeriodicWorkPolicy.KEEP,
            repeatingRequest
        )
    }
}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.moviemania">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application
        android:name=".MoviesApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MovieMania">
        <activity android:name=".ui.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="com.example.moviemania.workmanager-init"
            tools:node="remove" />
    </application>

</manifest>
Run Code Online (Sandbox Code Playgroud)

这是错误

2021-01-11 09:23:44.685 29929-29960/com.example.moviemania E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
    Process: com.example.moviemania, PID: 29929
    java.lang.NoSuchMethodError: No interface method getBackgroundExecutor()Ljava/util/concurrent/Executor; in class Landroidx/work/impl/utils/taskexecutor/TaskExecutor; or its super classes (declaration of 'androidx.work.impl.utils.taskexecutor.TaskExecutor' appears in /data/app/com.example.moviemania-6m_-4lzXG2Ud-HIb1asUiQ==/base.apk)
        at androidx.work.CoroutineWorker.<init>(CoroutineWorker.kt:52)
        at com.example.moviemania.work.RefreshDataWorker.<init>(RefreshDataWorker.kt:22)
        at com.example.moviemania.work.RefreshDataWorker_AssistedFactory.create(RefreshDataWorker_AssistedFactory.java:25)
        at com.example.moviemania.work.RefreshDataWorker_AssistedFactory.create(RefreshDataWorker_AssistedFactory.java:13)
        at androidx.hilt.work.HiltWorkerFactory.createWorker(HiltWorkerFactory.java:55)
        at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:83)
        at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:242)
        at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:136)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)

Hyo*_*won 12

从工作版本 2.6 开始,它可以使用下面的 androidmanifest.xml 工作

AndroidManifest.xml

<provider
     android:name="androidx.startup.InitializationProvider"
     android:authorities="${applicationId}.androidx-startup"
     tools:node="remove">
</provider>
Run Code Online (Sandbox Code Playgroud)

对于 Worker 类,一些注释已更改。@HiltWorker,@AssistedInject

@HiltWorker
class RefreshWorker @AssistedInject constructor(
    @Assisted appContext: Context,
    @Assisted workerParams: WorkerParameters,
    val myRepository: MyRepository
) : CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        return Result.success()
    }

}
Run Code Online (Sandbox Code Playgroud)

开发者网站(worker api) https://developer.android.com/jetpack/androidx/releases/hilt

将@WorkerInject 替换为@HiltWorker。@HiltWorker 现在是一个类型注释,需要在构造函数中使用 @AssistedInject。(IC2F15)

开发人员站点(删除默认工作初始化程序) https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration#remove-default

删除默认初始化程序 要提供您自己的配置,您必须首先删除默认初始化程序。为此,请使用合并规则工具更新 AndroidManifest.xml:node="remove"。

从 WorkManager 2.6 开始,App Startup 在 WorkManager 内部使用。要提供自定义初始化程序,您需要删除 androidx.startup 节点。

  • 您是否在 build.gradle 中添加了 kapt 'androidx.hilt:hilt-compiler:1.0.0' ? (3认同)

Abd*_*bri 8

我认为这是一个不正确的导入语句:这里是片段

请检查您的刀柄模块是否有错误的导入。

PS:我已经为你包含了进口

AndroidManifest.xml

    <application
    ...
        <provider
            android:name="androidx.work.impl.WorkManagerInitializer"
            android:authorities="${applicationId}.workmanager-init"
            tools:node="remove" />
    </application>
Run Code Online (Sandbox Code Playgroud)

我的应用程序.kt

import android.app.Application
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@HiltAndroidApp
class MyApplication : Application(), Configuration.Provider {
    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    private val applicationScope = CoroutineScope(Dispatchers.Default)

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .setMinimumLoggingLevel(android.util.Log.DEBUG)
            .build()


    override fun onCreate() {
        super.onCreate()
        delayedInit()
    }

    private fun delayedInit() {
        applicationScope.launch {
            setupRecurringWork()
        }
    }

    private fun setupRecurringWork(){
        val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS).build()

        WorkManager.getInstance(applicationContext).enqueueUniquePeriodicWork(
            RefreshDataWorker.WORK_NAME,
            ExistingPeriodicWorkPolicy.KEEP,
            repeatingRequest
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

刷新DataWorker.kt

import android.content.Context
import androidx.hilt.Assisted
import androidx.hilt.work.WorkerInject
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import java.lang.Exception

class RefreshDataWorker @WorkerInject constructor (
    @Assisted appContext: Context,
    @Assisted params: WorkerParameters,
    private val mainRepository: MainRepository
    ) : CoroutineWorker(appContext,params) {

    companion object {
        const val WORK_NAME = "com.example.moviemania.work.RefreshDataWorker"
    }

    override suspend fun doWork(): Result {
        try {
            mainRepository.refreshMovies()
        }catch (e: Exception){
            return Result.retry()
        }
        return Result.success()
    }
}
Run Code Online (Sandbox Code Playgroud)

主存储库.kt

import android.util.Log
import javax.inject.Inject

class MainRepository @Inject constructor() {
    fun refreshMovies() {
        Log.d("ManoO", "Hello first time from worker: initiated immediately")
    }
}
Run Code Online (Sandbox Code Playgroud)

摇篮脚本

项目
buildscript {
    ...

    dependencies {
        ...
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21"
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.30.1-alpha'
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序

dependencies {
    ....

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"

    implementation "com.google.dagger:hilt-android:2.30.1-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.30.1-alpha"
    implementation 'androidx.hilt:hilt-work:1.0.0-alpha02'
    kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'

    def work_version = "2.5.0-beta02"
    implementation "androidx.work:work-runtime-ktx:$work_version"

}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢分配..这是关于工作管理器的依赖性..我正在使用实现“android.arch.work:work-runtime-ktx:$work_version”而不是实现“androidx.work:work-runtime-ktx:$work_version ” (3认同)