как сделать запрос API внутри WorkManager?

#android #kotlin-coroutines #android-workmanager #dagger-hilt

Вопрос:

Я пытаюсь использовать WorkManager для периодического получения количества уведомлений из API, проблема в том, что я использую hilt для внедрения зависимостей, поэтому я не могу ввести в свой репозиторий «@Inject», даже если я использовал @AndroidEnteryPoint. И как я могу наблюдать за полученными данными внутри функции «DoWork».

     class NotificationsCountWorker
    (
    val context: Context,
    workerParams: WorkerParameters) :
    CoroutineWorker(context, workerParams) {


    @Inject lateinit var repo: RepositoryImpl
   
    
    override suspend fun doWork(): Result {
        Log.d(TAG, "doWork")
        //subscribeObserver()
        return try {
            withContext(Dispatchers.IO) {
                try {
                    Log.d(TAG, "inside with context")
                    repo.notificationsCount().onEach {
                        Log.d(TAG, "item; $it")
                    }.launchIn(this)
                    Log.d(TAG, "notif count ")
                    Result.success()

                } catch (e: Exception){
                    Log.d(TAG, "exception ${e.message}")
                    Result.failure()
                }
            }
        }catch (e:Exception){
            Log.d(TAG, "exception ${e.message}")
            Result.failure()
        }


}


    companion object {
    private const val TAG = "NotificationsWorkManger"
    const val NOTIFICATIONS_COUNT_WORK_MANGER_ID = "automatic_notifications_count_manger"
    fun reminder() {
        val periodicRefreshRequest = PeriodicWorkRequest.Builder(
            NotificationsCountWorker::class.java, // Your worker class
            15, // repeating interval
            TimeUnit.MINUTES
        )

        val periodicWorkRequest: PeriodicWorkRequest = periodicRefreshRequest
            .build()
        WorkManager.getInstance(getApplication()).enqueueUniquePeriodicWork(
            NOTIFICATIONS_COUNT_WORK_MANGER_ID,
            ExistingPeriodicWorkPolicy.REPLACE,
            periodicWorkRequest
        )
    }
}


}
 

Комментарии:

1. Вы используете конкретную интеграцию между Hilt и WorkManager ?

2. Я не внедряю менеджер работ, я пытаюсь только внедрить в него репозиторий, но даже когда я следовал определенной интеграции, это ничего не изменило

3. Как вы думаете, что делает интеграция между Hilt и WorkManager, кроме как позволяет вам внедрить репозиторий в вашего работника? Это именно тот пример, который приведен в документах.

4. да, я сделал это после вашего первого сообщения, и я следил за документацией, но это все та же проблема, которая поздно, но еще не инициирована

Ответ №1:

Вам нужно внедрить свои зависимости через конструктор. Для того, чтобы сделать инъекцию Рабочему с рукояткой, вам нужно сделать следующее.

Во-первых, аннотируйте своего рабочего, его конструктор и аргументы конструктора как таковые:

 @HiltWorker
class MyWorker @AssistedInject constructor(
    @Assisted context: Context,
    @Assisted workerParameters: WorkerParameters,
    private val repository: Repository
) : CoroutineWorker(context, workerParameters)
 

Вы должны только аннотировать context и workerParameters как @Assisted . Все остальные ваши зависимости разрешаются с помощью Hilt, они должны быть установлены SingletonComponent или не иметь области видимости.

Затем внедрите HiltWorkerFactory в свой основной Application производный класс и сделайте так, чтобы этот класс реализовывал Configuration.Provider интерфейс следующим образом:

 @HiltAndroidApp
class MainApplication : Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    override fun getWorkManagerConfiguration() =
        Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}
 

Последний шаг — отключить инициализацию WorkManager по умолчанию. Для этого вставьте эти строки в свой AndroidManifest.xml , если вы используете WorkManager версии 2.6.0-alpha01 или выше:

 <provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <!-- If you are using androidx.startup to initialize other components -->
    <meta-data
        android:name="androidx.work.impl.WorkManagerInitializer"
        android:value="androidx.startup"
        tools:node="remove" />
</provider>
 

или

 <!-- If you want to disable android.startup completely. -->
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    tools:node="remove">
</provider>
 

Если вы используете более старые версии, вам следует добавить это:

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

Комментарии:

1. Привет, спасибо, я ценю ваш ответ, это то, что я ищу.