[Android] Jetpack WorkManager

2024. 1. 7. 17:08·Android

📕 WorkManager란?

 Android Jetpack Library의 WorkManager는 Background Task를 위해 만들어졌습니다.

 

안드로이드 M(API 23) 부터 Background Task 제약 사항들이 점차 추가되며 개발자들은 Service, JobSchduler, JobDispatcher등을 사용해 개발했지만 API의 문제들로 인해 WorkManager가 등장하게 되었습니다. 이 글에선 기존 API의 문제점과 Workmanager에 대해 알아보겠습니다.


🤔 Background 상태의 앱이 왜 자동으로 종료될까요 ?

안드로이드 커널은 리눅스 커널은 기반으로 개발 되었지만 가장 큰 차이점은 Swap Space가 존재하지 않습니다.

 

📌Swap Space 

  • 주기억장치(RAM)의 용량이 부족할 때 비활성화 된 메모리를 HDD로 이동시킵니다.
  • 이 때, HDD의 일부 공간을 Swap Space로 제공합니다.
  • HDD는 RAM에 비해 속도가 느리기 때문에 성능에 영향을 미칠 수 있습니다.
  • 대표적인 스왑 알고리즘으로 LRU(Least Recently Used)이  있습니다.

 

안드로이드는 기본적으로 Swap Space가 없습니다. LKM(Low Memory Killer) OOM(Out of Memory) Killer를 사용해 프로세스를 강제 종료 시킵니다. 자세한 내용은 아래글을 참조해 주세요 !

 

 

[Android]Android Memory Process

[안드로이드 공식 문서] 프로세스 간 메모리 할당 | App quality | Android Developers 프로세스 간 메모리 할당 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Android

chanho-study.tistory.com

📌Background Task

1️⃣ Service 

안드로이드를 처음 공부할 때 안드로이드 4대 컴포넌트 중 Service는 백그라운드 작업을 수행한다고 배웠습니다. 그 외에 서비스를 사용해야 하는 이유는 뭐가 있을까요 ?

  • 시스템에게 해당 프로세스가 오래 걸리는 작업임을 알립니다.
  • 서비스를 사용함으로써 알맞은 oom_adj_score를 부여합니다.
  • 독립적인 프로세스에서 동작을 실행할 수 있습니다.

이 중 "독립적인 프로세스에서 동작을 실행할 수 있습니다." 이 부분이 바로 서비스에서 문제를 발생시킵니다. 별도의 프로세스에서 동작한다는 것은 배터리를 많이 소모시킵니다.  이를 해결하기 위해 구글은 "Doze 모드"를 도입하였고 구글은 앱 마켓에 등록할 수 있는 앱에 제약을 하나씩 추가 하며 점점 발전시켰습니다.

 

이에 Service를 대체하기 위해 나온것이 Job API 입니다.

 

2️⃣ Job

잡 스케쥴러는 안드로이드 5버전(API Lv21) 부터 제공했지만 안드로이드 8 버전부터 백그라운드 제약이 생기며 더욱 중요했습니다. JobScheduler를 사용하여 일정한 간격으로 또는 특정 조건이 충족될 때 실행되어야 하는 작업을 예약할 수 있습니다.

 

🔨 잡 스케쥴러의 3가지 구성 요소

  • 잡 서비스 : Background Task를 구현한 서비스 입니다.
  • 잡 인포 : 잡 서비스 정보와 실행될 조건을 지정합니다.
  • 잡 스케쥴러 : 잡 인포를 시스템에 등록합니다.

이후 버그가 너무 많아 JobDispatcher로 대체됩니다.

 

하지만 JobDispatcher 또한 제대로 동작하지 않는 기기가 있기 때문에

 

이후 JobIntentService로 대체됩니다.

 

하지만 JobIntentService 또한 원하는 타이밍에 딱 맞게 동작하지 않는 문제가 있었기 때문에

 

WorkManager가 등장하게 됩니다.

 

2️⃣ WorkManager

  • 시스템 기반의 Background Processing API를 제공하여 구현을 단순화 할 수 있도록 도와줍니다.
  • 앱이 포그라운드에 없더라도 백그라운드에서 Job이 수행될 수 있도록 합니다.
  • 개발자가 백그라운드 처리과정을 신경쓰지 않아도 되도록 합니다.
  • 그렇기 때문에 Service, JobIntentService 등 대부분의서비스 기능을 대체 가능합니다
  • 짧은 작업, 오래 걸리는 작업 모두 사용가능합니다.
  • 네트워크 상태, 배터리 상태 등으로 트리거가 가능합니다.
  • 포그라운드에서도 사용 가능합니다.
  • FCM과 같이 사용할 수 있습니다.

🔨 workerManager Component

  • WorkManager
    처리해야 하는 작업을 자신의 큐에 넣고 관리합니다. 싱글톤으로 구성되어 getInstance()로 WorkManager의 인스턴스를 받아 사용합니다.
  • Worker
    • 추상 클래스이며, 처리해야 하는 백그라운드 작업의 처리 코드를 이 클래스를 상속받아 doWork() 메서드를 오버라이드 하여 작성하게 됩니다.
      • doWork()
        • 작업을 완료하고 결과에 따라 Worker클래스 내에 정의된 enum인 Result의 값중 하나를 리턴
        • SUCCESS, FAILURE, RETRY의 3개 값이 있으며 리턴되는 이 값에 따라 WorkManager는 해당 작업을 마무리 할것인지, 재시도 할것인지, 실패로 정의하고 중단할 것인지를 결정
  • WorkRequest
    • WorkManager를 통해 실제 요청하게 될 개별 작업
    • 처리해야 할 작업인 Work와 작업 반복 여부 및 작업 실행 조건, 제약 사항등 이 작업을 어떻게 처리할 것인지에 대한 정보가 담겨있습니다
    • 반복여부에 따라 onTimeWorkRequest, PeriodicWorkRequest로 나뉜다
    • onTimeWorkRequest
      • 반복하지 않을 작업, 즉 한번만 실행할 작업의 요청을 나타내는 클래스
    • PeriodicWorkRequest
      • 여러번 실행할 작업의 요청을 나타내는 클래스
  • WorkState
    • WorkRequst의 id와 해당 WorkRequest의 현재 상태를 담는 클래스
    • 이 WorkState의 상태정보를 이용해서 자신이 요청한 작업의 현재 상태를 파악할 수 있다
    • ENQUEUED, RUNNING, SUCCEEDED, FAILED, BLOCKED, CANCLLED의 6개 상태를 가진다

📌 기본 WorkManager 생성

val workManagerA = OneTimeWorkRequestBuilder<WorkManagerA>().build()
WorkManager.getInstance(this).enqueue(workManagerA)

class WorkManagerA(context: Context, workerParameters: WorkerParameters)
    : Worker(context, workerParameters) {

    override fun doWork(): Result {
        for (i in 1..10){
            sleep(1000)
            Log.d("WorkManagerA", i.toString())
        }
        return Result.success()
    }

}

 

📌 WorkManager 데이터 전달

  • inputData.getInt(key, default Value) : Activity나 Fragment에서 전달한 데이터를 받습니다.
  • setInputData( ) : Data Type의 데이터를 전달합니다.
  • workDataof ( ): key와 value 형태로 데이터를 전달합니다.
class WorkManagerB(context: Context, workerParameters: WorkerParameters)
    : Worker(context, workerParameters) {

    override fun doWork(): Result {

        val a = inputData.getInt("a", 1000)
        val b = inputData.getInt("b", 2000)
        val c = inputData.getInt("c", 3000)

        Log.d("WorkManagerB", a.toString())
        Log.d("WorkManagerB", b.toString())
        Log.d("WorkManagerB", c.toString())

        val output: Data = workDataOf("result" to 10)

        return Result.success(output)
    }

}

val myData: Data = workDataOf(
 "a" to 10,
  "b" to 20
)
val workManagerB = OneTimeWorkRequestBuilder<WorkManagerB>().setInputData(myData).build()
WorkManager.getInstance(this).enqueue(workManagerB)

 

📌 WorkManager channing

workManager 의 작업 순서를 정합니다.

val workManagerC = OneTimeWorkRequestBuilder<WorkManagerC>().build()
val workManagerD = OneTimeWorkRequestBuilder<WorkManagerD>().build()
val workManagerE = OneTimeWorkRequestBuilder<WorkManagerE>().build()

WorkManager.getInstance(this)
    .beginWith(listOf(workManagerC, workManagerD))
    .then(workManagerE)
    .enqueue()

 

 

📌 WorkManager + Coroutine

class WorkManagerF(context: Context, workerParameters: WorkerParameters)
    : CoroutineWorker(context, workerParameters) {

    override suspend fun doWork(): Result {

        return Result.success()
    }

    suspend fun test1(){
        for (i in 1..3){
            delay(1000)
            Log.d("CoroutineWorker", i.toString())
        }
    }

    suspend fun test2(){
        for (i in 1..3){
            delay(1000)
            Log.d("CoroutineWorker", i.toString())
        }
    }
}

 

 

'Android' 카테고리의 다른 글

[Android] Room TypeConverter  (0) 2024.01.21
[Android] Room Database  (1) 2024.01.21
[Android]Android Memory Process  (1) 2024.01.07
Android Daum 우편번호 서비스 API With FireBase Hosting  (2) 2024.01.04
Android Base64 Decoding  (0) 2024.01.03
'Android' 카테고리의 다른 글
  • [Android] Room TypeConverter
  • [Android] Room Database
  • [Android]Android Memory Process
  • Android Daum 우편번호 서비스 API With FireBase Hosting
빨주노초잠만보
빨주노초잠만보
  • 빨주노초잠만보
    과거의 나를 통해 미래의 나를 성장시키자
    빨주노초잠만보
  • 전체
    오늘
    어제
    • 분류 전체보기 (97)
      • TEKHIT ANDROID SCHOOL (4)
      • Android Architecture (7)
      • Android (41)
      • PROJECT (5)
      • KOTLIN (10)
        • 코루틴의 정석 (3)
      • BACK END (12)
      • CS (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    sealed class
    httpservicemethod
    retrofit interface
    kotlin interface abstract 차이
    Throttle
    retrofit service interface
    2025 드로이드 나이츠
    repository
    DI
    DataSource
    flow
    retrofi response
    코틀린 코루틴의 정석
    retrofit call
    Repository Pattern
    Clean Architecture
    orbit
    STATEFLOW
    value class
    Livedata
    retrofit parseannotations
    parseannotations
    callbackflow
    의존성 주입
    리사이클러뷰 풀
    MVI
    ThrottleFirst
    Room
    android Room
    android clean architecture
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
빨주노초잠만보
[Android] Jetpack WorkManager
상단으로

티스토리툴바