안드로이드 work manager

이영준·2022년 11월 3일
0

WorkManager는 안드로이드의 백그라운드 작업을 관리하기 위한 시스템으로 안드로이드 제트팩에서 나왔다. 백그라운드 작업을 스케쥴링 할 수 있고, 앱의 종료에도 이 작업의 실행 유지를 보장해준다고 한다.
https://proandroiddev.com/experiments-with-android-workmanager-our-new-reliable-assistant-for-deferrable-background-work-9baeb6bd7db3

Create a Worker class -> create work request -> enque the request -> get status updates의 4단계로 스케쥴링이 이루어진다.
참고 최소 API 레벨은 26이 되어야 한다.

초기설정

https://developer.android.com/topic/libraries/architecture/workmanager/basics

work manager dependency 세팅을 가져온다.

 def work_version = "2.7.1"
    implementation "androidx.work:work-runtime-ktx:$work_version"

Worker Class

백그라운에서 작업할 로직을 작성해주는 클래스이다.

이 클래스는 Worker 객체를 상속받아 작성되어야 하고, doWork라는 필수 멤버 메서드를 오버라이딩 해야 한다.

class UploadWorker(context: Context, params: WorkerParameters) : Worker(context,params) {
    override fun doWork(): Result {

        try {
            for (i in 0..600) {
                Log.i("MYTAG", "Uploading $i")
            }
            return Result.success()
        } catch (e: Exception) {
            return Result.failure()
        }
    }
}

0~600까지는 로그에 띄워주는 함수를 작성하였다.

OneTimeWorkRequest builder

private fun setOneTimeWorkRequest(){
        val uploadRequest = OneTimeWorkRequest.Builder(UploadWorker::class.java)
            .build()
        WorkManager.getInstance(applicationContext)
            .enqueue(uploadRequest)
    }

main에서 위와 같이 빌더를 만들어주고 worker class를 받아온다. 이 setOneTimeWorkRequest를 버튼에 onclick 함수로 넣어주면,

백그라운드 작업에서의 실행을 확인할 수 있다.

WorkInfo 확인하기

workManager의 작업 진행 경과를 liveData로 observing 할 수 있다.

실행함수를

    private fun setOneTimeWorkRequest(){
        val workManager = WorkManager.getInstance(applicationContext)
        val uploadRequest = OneTimeWorkRequest.Builder(UploadWorker::class.java)
            .build()
        workManager.enqueue(uploadRequest)
        workManager.getWorkInfoByIdLiveData(uploadRequest.id)
            .observe(this, Observer {
                binding.textView.text = it.state.name
            })
    }
}

위와 같이 변경해보았다. workManager 인스턴스에 getWorkInfoByIdLiveData(builder.id)를 확인하면 blocked, enqueued, running , succeeded 순으로 바뀌는 작업 상태를 확인할 수 있다.

Constraint (네트워크, 충전중 등 제약사항 주기)

constraints 는 작업의 규모가 클 때는 배터리가 많거나 충전중일 때만 작업을 실행하던지 하는 다양한 백그라운드 작업에 대비하여 걸어두는 제약사항이다.

사용방법은 아래와 같다.

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

그리고 그 작업에 enqueing 하는 uploadRequset에 .setConstraints 속성으로 넣어주면 된다.

    private fun setOneTimeWorkRequest(){
        val workManager = WorkManager.getInstance(applicationContext)
        val constraints = Constraints.Builder()
            .setRequiresCharging(true)
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()
        val uploadRequest = OneTimeWorkRequest.Builder(UploadWorker::class.java)
            .setConstraints(constraints)
            .build()
        workManager.enqueue(uploadRequest)
        workManager.getWorkInfoByIdLiveData(uploadRequest.id)
            .observe(this, Observer {
                binding.textView.text = it.state.name
            })
    }
}

WorkManager에서 데이터 주고 받기

intent로 다른 클래스나 프래그먼트로 데이터를 보내는 것과 거의 유사한 방식으로 workManager를 하면서 데이터도 주고 받을 수 있다.

먼저 main -> worker class

외부에서 데이터를 보낼 때 정의한 키를 사용할 수 있도록 companion object로

companion object{
        const val KEY_COUNT_VALUE = "key_count"
    }

키를 만들어주고,

val data : Data = Data.Builder()
            .putInt(KEY_COUNT_VALUE,125)
            .build()
val uploadRequest = OneTimeWorkRequest.Builder(UploadWorker::class.java)
            .setConstraints(constraints)
            .setInputData(data)
            .build()

UploadRequest에 setInputData메서드로 data를 담아서 UploadWorker 클래스에 전달한다.

Worker Class 에서는

class UploadWorker(context: Context, params: WorkerParameters) : Worker(context,params) {

    companion object{
        const val KEY_WORKER = "key_worker"
    }

    override fun doWork(): Result {

        try {
            val count = inputData.getInt(MainActivity.KEY_COUNT_VALUE,0)
            for (i in 0 until count) {
                Log.i("MYTAG", "Uploading $i")
            }
            val time = SimpleDateFormat("dd/M/yyyy hh;mm;ss")
            val currentDate = time.format(Date())
            val outPutData = Data.Builder()
                .putString(KEY_WORKER,currentDate)
                .build()

            return Result.success(outPutData)
        } catch (e: Exception) {
            return Result.failure()
        }
    }
}

마찬가지로 데이터를 보내기 위한 companion object를 만들고,

val count = inputData.getInt(MainActivity.KEY_COUNT_VALUE,0)

inputData를 감지하여 키에 해당하는 값을 가져온다.

이제 worker class -> main activity
데이터를 보내기 위해서는

val outPutData = Data.Builder()
                .putString(KEY_WORKER,currentDate)
                .build()

Data.Builder()안에 putString() 메서드로 데이터를 넣어주고,

return Result.success(outPutData)

result.success에 이를 담아주면 된다.

profile
컴퓨터와 교육 그사이 어딘가

0개의 댓글