안드로이드 개발일기
[WorkManager + Flow] doWork 후 flow의 onCompletion이 호출되지 않는다 본문
구현하고자 하는 기능
- 앱이 백그라운드에서 task를 수행하고, 완료되면 이벤트를 받아서 추후 로직을 수행한다.
-> 앱이 종료되어도 재실행시 계속 수행해야 하므로 WorkManager를 사용
-> 이벤트 수신을 위해 WorkManager.getWorkInfoByIdFlow를 사용
로직
1. UseCase에서 WorkRequest를 만들고 WorkManager.enqeue에 넣는다.
2. WorkManager의 일이 끝나면 이벤트를 받기 위해 Flow를 사용한다.
3. 호출한 UseCase의 메소드는 WorkManager의 수행 완료 값을 가지고 Flow 형태로 반환한다.
4. viewModel은 이를 consume하여 추후 로직을 수행한다.
코드
UseCase
suspend fun doTask(): Flow<WorkInfo> {
...
val workRequest = OneTimeWorkRequestBuilder<ImageUploadWorker>()
.setInputData(inputData)
.setConstraints(constraints)
.build()
...
workManager.enqueue(workRequest)
return workManager.getWorkInfoByIdFlow(workRequest.id)
}
Worker
class TaskWorker(
private val context: Context,
params: WorkerParameters
): CoroutineWorker(context, params) {
...
override suspend fun doWork(): Result {
...
/*태스트 수행~*/
return if (isSuccess) {
Result.success(
Data.Builder()
...
.build()
)
} else {
Result.failure()
}
}
}
ViewModel
private fun requestDoTask() {
viewModelScope.launch {
usecase.doTask()
.onStart { showLoading() }
.onCompletion { hideLoading() }
.collectLatest { workInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED) {
...
}
}
}
}
문제
저는 Worker가 doWork를 끝내고 Result를 반환하면 collectLatest에서 추후 로직을 수행하면 되고, 마지막으로 onCompletion에서 화면에 노출 중이던 로딩을 지우려고 했습니다.
하지만 collectLatest로 workInfo는 받았지만 onCompletion이 호출되지 않아 로딩이 계속 돌아가는 문제가 생겼습니다.
관련 서치 내용
1. onCompletion은 Flow에서 모든 작업이 완료되고, 에러 없이 성공적으로 모든 데이터가 발행되었을 때 호출된다.
-> 따라서 Worker가 끝났지만 onCompletion이 호출되지 않는다면
- Flow가 아직 완료되지 않았거나
- 에러로 인해 비정상적으로 종료되었는지
를 확인해보아야 한다.
나는 catch 블록이 타지 않는 것을 확인하여 에러가 발생한 것은 아니었다.
2. WorkManager.getFlowInfoByFlow()는 workRequest가 끝났다고 flow가 바로 종료되는 것은 아니다.
(추측)
이미 WorkManager.enqueue()에 넣은 WorkRequest를 update하는 메소드가 있는 것으로 보아, WorkManager는 Worker가 종료되더라도 어떠한 이벤트가 발생할 수 있다는 가능성을 열어두고 바로 flow를 종료하지 않는 것이 아닐까 생각한다.
'android' 카테고리의 다른 글
[TIL] Jetpack Compose remember와 rememberSavable (0) | 2025.04.01 |
---|---|
[Firebase] AppCheck 적용하기 (Play Integrity) (0) | 2024.09.07 |
[Android] PDF 로드 및 관리 with Compose (0) | 2024.03.23 |
[Clean Architecture] UseCase를 사용하는 이유 (0) | 2023.12.14 |
[Android] Retrofit multiple API 결합하기 (Flow combine 사용) (0) | 2023.09.12 |