WorkManager
는 지속적으로 작업을 실행하기 위해 사용하는 API다. 앱 및 시스템을 재시작해도 작업을 유지할 수 있으므로 JobScheduler
를 대체할 수 있다. 일반적으로 백그라운드에서 실행하는 작업을 지속해야 하기 때문에 백그라운드 작업을 실행할 때 사용하기를 권장하는 API다.
WorkManager
가 관리하는 작업의 유형은 다음과 같다.
- 즉시 실행
- 장시간 실행
- 지연 가능
Worker로 작업 단위 정의하기
Worker
추상 클래스의 하위 클래스를 정의하여 작업 단위를 정의한다. 실행하고자 하는 작업의 로직은 doWork()
를 재정의하여 구현한다. doWork()
는 ListenableWorker.Result
인스턴스를 반환하는데 이는 작업의 성공 여부를 나타내며 다음 3가지 경우로 나뉜다.
Result.success()
작업 성공Result.failure()
작업 실패Result.retry()
작업 실패 + 설정된 재시도 정책에 따라 나중에 재시도
class UploadWorker(
appContext: Context,
workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
// 작업 로직
uploadImages()
// 작업 성공 여부 반환
return Result.success()
}
}
WorkRequest 생성하기
WorkRequest
는 WorkManager
에 예약할 작업에 대한 정보를 포함하는 클래스다. Builder
클래스를 사용하여 인스턴스를 생성하며 다음 사항들을 설정할 수 있다.
- 작업 태그 및 ID
- 중요한 작업인지 여부
- 초기 지연 시간
- 제약 조건
- 백오프 정책 및 지연 시간
- 작업 결과 유지 시간
- 작업을 실행하는 데 필요한 데이터
WorkRequest
는 추상 클래스이다. 작업 유형에 따라 하위 클래스인 OneTimeWorkRequest
또는 PeriodicWorkRequest
를 사용한다.
일회성 작업
한 번만 실행할 작업에 대한 WorkRequest
는 OneTimeWorkRequest
를 사용한다. OneTimeWorkRequest.Builder
객체를 생성하는 방법은 2가지로 나뉜다.
추가 설정이 필요 없을 정도로 작업이 간단한 경우 OneTimeWorkRequest.from(Class<out ListenableWorker>)
를 사용한다.
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
복잡한 경우 Builder
클래스를 사용한다. Kotlin을 사용하는 경우 OneTimeWorkRequestBuilder
메서드를 사용할 수 있다.
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
// 추가 설정
.build()
주기적으로 실행되는 작업
주기적으로 실행할 작업에 대한 WorkRequest
는 PeriodicWorkRequest
를 사용한다. PeriodicWorkRequest
객체는 Builder
클래스를 사용하여 생성한다. Kotlin을 사용하는 경우 PeriodicWorkRequestBuilder
메서드를 사용할 수 있다. 파라미터는 작업 실행 주기에 대한 정보를 나타낸다.
val saveRequest =
PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
// 추가 설정
.build()
가변 실행 간격
작업을 각 실행 주기 내의 가변 주기(flex period) 내에 실행하도록 할 수 있다.
작업 실행 주기 및 가변 주기를 설정하려면 PeriodicWorkRequest.Builder
객체를 생성할 때 이에 대한 정보를 파라미터로 전달해야 한다. 다음은 작업 실행 주기가 1시간이고 그 중 가변 주기가 마지막 15분인 주기 작업 예시다.
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // 작업 실행 주기와 시간 단위
15, TimeUnit.MINUTES) // 가변 주기와 시간 단위
.build()
작업 제약 조건
작업을 실행하기 위해 충족시켜야 하는 제약 조건을 설정할 수 있다. WorkManager
에서 사용할 수 있는 제약 조건은 다음과 같다.
NetworkType
작업 실행 시 필요한 네트워크 유형을 제한한다.BatteryNotLow
true
로 설정하면 배터리 부족 상태에서 작업이 실행되지 않는다.RequiresCharging
true
로 설정하면 충전 중이어야 작업이 실행된다.DeviceIdle
true
로 설정하면 디바이스가 유휴 상태이어야 작업이 실행된다.StorageNotLow
true
로 설정하면 저장공간이 부족하지 않아야 작업이 실행된다.
제약 조건은 Constraints.Builder
클래스를 통해 생성된 Constraints
객체에 포함된다. 이 Constraints
객체를 WorkRequest.Builder#setConstraints(Constraints)
에 전달하면 작업에 제약 조건이 설정된다. 다음은 충전 중이고 Wi-Fi가 연결되어 있어야 실행되는 작업 예시다.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build()
val myWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setConstraints(constraints)
.build()
제약 조건이 설정된 작업은 조건을 모두 충족해야 실행된다. 작업을 이미 실행 중인 도중에 조건을 충족하지 못하게 되는 경우 작업이 중단된다. 그러고 나서 조건을 모두 충족하게 될 때 작업을 재시도한다.
작업 딜레이
작업을 WorkManager
에 예약할 때 제약 조건이 없거나 모두 충족하는 경우 시스템이 작업을 즉시 실행할 수 있다. 하지만 즉시 실행하지 않고자 한다면 초기에 작업이 지연되는 시간을 설정할 수 있다. WorkRequest.Builder#setInitialDelay(Long, TimeUnit)
에 지연 시간 및 시간 단위를 전달한다. 다음은 10분 지연된 뒤 실행되는 일회성 작업 예시다.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
재시도 및 백오프 정책
작업을 재시도해야 하는 경우 Worker#doWork()
에서 Result.retry()
를 반환한다. 그러고 나서 백오프 딜레이 및 정책에 따라 작업을 재시도한다.
- 백오프 딜레이
작업을 처음으로 재시도하기 전 대기해야 하는 시간을 나타낸다. - 백오프 정책
작업 재시도 횟수가 증가함에 따라 백오프 딜레이가 증가하는 방식을 나타낸다.BackoffPolicy.LINEAR
과BackoffPolicy.EXPONENTIAL
을 사용할 수 있다.
기본 백오프 딜레이는 10초이며 기본 백오프 정책은 EXPONENTIAL
이지만 WorkRequest.Builder#setBackoffCriteria(BackoffPolicy, Long, TimeUnit)
를 사용하여 재정의할 수 있다.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setBackoffCriteria(
// 백오프 정책: 선형
BackoffPolicy.LINEAR,
// 백오프 딜레이: 10초 (단위 고려 필요)
OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
// 시간 단위: ms
TimeUnit.MILLISECONDS)
.build()
작업 ID 및 태그
모든 WorkRequest
에는 ID가 있기 때문에 작업 취소 및 진행 상황 모니터링을 하는 데 사용할 수 있다. WorkRequest
의 ID는 WorkRequest.Builder#setId(UUID)
를 사용하여 설정하고 WorkRequest.id
프로퍼티로 확인할 수 있다.
서로 관련된 작업 항목에 태그를 추가할 수 있다. 같은 태그를 설정한 작업 항목을 함께 실행하거나 취소할 수 있다. 작업 항목에 태그를 추가하려면 WorkRequest.Builder#addTag(String)
을 사용하면 된다.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.addTag("cleanup")
.build()
입력 데이터
작업을 실행할 때 입력 데이터가 필요한 경우가 있다. 입력 데이터는 Data
객체를 사용한다.
Data
는 내부의 Map<String, Object>
에 데이터를 저장한다. Data
객체는 Data.Builder
클래스를 사용하여 생성한다. workDataOf(vararg Pair<String, Any?>)
함수로도 생성할 수 있다.
val myUploadWorkRequest = OneTimeWorkRequestBuilder<UploadWork>()
.setInputData(
workDataOf("IMAGE_URI" to "http://..."))
.build()
작업 로직에서 Worker#getInputData()
를 호출하여 입력 데이터에 액세스할 수 있다.
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()
}
...
}
'Android' 카테고리의 다른 글
WorkManager (3) : 작업 관리하기 (0) | 2022.12.05 |
---|---|
WorkManager (2) : 작업 상태 (0) | 2022.12.02 |
DataStore (0) | 2022.11.30 |
Lifecycle (0) | 2022.11.11 |
데이터 바인딩 (4) : 양방향 바인딩 (0) | 2022.11.05 |