오늘도 더 나은 코드를 작성하였습니까?

WorkRequest 만들기. 본문

Android Jetpack Architecture/Workmanager

WorkRequest 만들기.

hik14 2021. 3. 12. 12:02

Worker에서는 어떤 작업을 수행할지를 정의한다면, WorkRequest에서는 정의된 작업을  몇 번 언제 어떻게 할 것인지를 정의한다.

 

  • 일회성 및 반복 작업 예약
  • Wi-Fi 또는 충전과 같은 작업 제약조건 설정
  • 작업 실행의 최소 지연 보장
  • 재시도 및 백오프 전략 설정
  • 작업에 입력 데이터 전달
  • 태그를 사용하여 관련 작업 그룹화

Work(작업정의) ---> WorkRequest(제약조건, 지연 또는 반복 간격과 같은 예약 정보, 재시도 구성) ---> WorkManager(예약 및 실행)

 

WorkRequest 자체는 추상적인 기본 클래스이다

 

OneTimeWorkRequest 일회성(반복 없음) 작업을 예약

 

추가적인 구성이 필요없는 경우 

val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

추가적 구성(지연, 데이터 넘기기, 제약 등)이 필요하면 Builer를 사용한다. 

val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

 

PeriodicWorkRequest 일정 간격의 반복 작업을 예약

val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

가변실행 간격 생성 -  실행주기를 정하고 그 주기안에서 가변적인 시간에 실행된다. 

 

가변 기간으로 주기적 작업을 정의하려면 PeriodicWorkRequest를 만들 때 flexInterval repeatInterval과 함께 전달한다.

가변 기간은 repeatInterval - flexInterval에서 시작하여 간격 끝으로 이동합니다

val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

 1시간 마다 실행하되  1시간내 마지막 15분에 가변적으로 실행한다. 

 

최소 반복 간격은 PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS 이상이어야 하고

최소 가변 간격은 PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS 이상이어야 합니다.

 

제약 조건 생성하기

사용자의 기기가 충전 중일 때만 작업이 실행되도록 작업 요청에 제약조건을 추가할 수 있습니다. 이 경우 정의된 반복 간격이 지나도 PeriodicWorkRequest는 조건이 충족될 때까지 실행되지 않습니다.

이로 인해 작업의 특정 실행이 지연되거나, 실행 간격 내에 조건이 충족되지 않으면 생략될 수도 있습니다.

 

Contraints.Builder()를 사용하여 Constraints ---> WorkRequest.Builder()

val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

제약이 여러개면 전부 충족되어야 실행된다.

작업 실행 중에 제약조건이 충족되지 않는 경우 WorkManager에서 작업자를 중지합니다.

그런 다음 모든 제약조건이 충족될 때 작업을 다시 시도합니다.

 

지연시켜 작업 실행하기

작업이 큐에 추가될 때 작업에 제약조건이 없거나 모든 제약조건이 충족되는 경우 시스템에서 즉시 작업을 실행하기로 선택할 수 있습니다. 작업을 즉시 실행하지 않으려면 최소 초기 지연 후 시작하도록 작업을 지정할 수 있습니다.

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES) // 초기 지연 10분을 주었다. 
   .build()

 

OneTimeWorkRequest의 초기 지연을 설정하는 방법을 보여주지만 PeriodicWorkRequest의 초기 지연을 설정할 수도 있습니다. 이 경우 주기적 작업의 첫 번째 실행만 지연됩니다

 

작업을 재시도 정책 만들기

WorkManager에서 작업을 다시 시도해야 하는 경우 Worker의 dowork() 에서 Result.retry()를 반환한다.

그러면 백오프 지연  백오프 정책에 따라 작업이 다시 예약됩니다.

 

 

- 백오프 지연은 첫 번째 시도 후 작업을 다시 시도하기 전에 기다릴 최소 시간을 지정합니다.

이 값은 10초(또는 MIN_BACKOFF_MILLIS) 미만일 수 없습니다.

 

-백오프 정책은 다음 재시도의 백오프 지연이 시간 경과에 따라 증가하는 방법.

WorkManager에서는 두 가지 백오프 정책 LINEAR, EXPONENTIAL을 지원합니다.

 

모든 WorkRequest에는 백오프 정책과 백오프 지연이 정의되어 있다..

기본 정책은 10초 지연이 있는 EXPONENTIAL이지만 작업 요청 구성에서 재정의할 수 있습니다.

val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setBackoffCriteria(
       BackoffPolicy.LINEAR,
       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
       TimeUnit.MILLISECONDS)
   .build()

LINEAR - 10초 뒤에 재시도, 20초 뒤에 재시도 30초 뒤에 재시도,  1차함수 처럼 선형 증가

EXPONENTIAL -10초 뒤에 재시도, 20초 뒤에 재시도, 40, 80, 160..... 지수적인 증가.

태그 만들기

모든 WorkRequest은 id를 가지고 있다.

id를 이용하여 작업취소 및 어떻게 진행 되는지 확인할 때 이용한다.

 

논리적으로 관련된 작업 그룹이 있다면 이러한 작업 항목에 태그를 지정하는 것도 유용하다.

태그를 사용하면 작업 요청 그룹을 함께 실행할 수 있습니다.

 

WorkManager.cancelAllWorkByTag(String) - 특정 태그가 있는 모든 작업 요청을 취소

WorkManager.getWorkInfosByTag(String) - 현재 작업 상태를 확인하는 데 사용할 수 있는 WorkInfo 객체 목록을 반환

 

단일 작업 요청에 여러 태그를 추가 가능하며 내부적으로 이러한 태그는 문자열 집합으로 저장됩니다. 작업 요청에

WorkRequest.getTags()를 통해 태그 집합을 알 수 있다.

입력된 데이터 할당하기

작업을 실행하려면 입력 데이터가 작업에 필요할 수 있다.

예를 들어 이미지 업로드를 처리하는 작업은 이미지의 URI를 입력으로 업로드해야 할 수 있다.

 

입력 값은 Data 객체에 키-값 쌍으로 저장되고 WorkRequest에 구성할때 넣어줄 수있다.

WorkManager에서는 작업을 실행할 때 작업에 입력 Data를 제공해준다.

Worker 클래스는 Worker.getInputData()를 호출하여 키값을 통해 데이터를 받을수 있다. 

// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

 

작업을 완료하고 Reult.success(Data)를 사용하여 반환 값을 출력할 수 도있다.