๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/Android

[Android] WorkManager - ์ธ์ž ์ „๋‹ฌ ๋ฐ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜

interfacer_han 2024. 6. 17. 20:09

#1 ์ด์ „ ๊ธ€

 

[Android] WorkManager - ๊ธฐ์ดˆ

#1 ์ด์ „ ๊ธ€ [Android] WorkManager - ๊ฐœ์š”#1 WorkManager๋Š” '์ง€์—ฐ ๊ฐ€๋Šฅํ•œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…'์˜ ๊ด€๋ฆฌ์ž WorkManager๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… - Kotlin | Android DevelopersAndroid์—๋Š” ๋ณด์žฅ๋œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—…์„ ์œ„ํ•œ ๋‹ค

kenel.tistory.com

์œ„ ๊ฒŒ์‹œ๊ธ€์˜ ์™„์„ฑ๋œ ์•ฑ์„ ์ผ๋ถ€ ์ˆ˜์ •ํ•ด์„œ, Worker์— ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜๊ณ  Worker๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›์•„ ๋ณธ๋‹ค.

 

#2 ์ฝ”๋“œ ์ˆ˜์ •

#2-1 MainActivity - setOneTimeWorkRequest()

...

class MainActivity : AppCompatActivity() {

    companion object {
        const val KEY_LUCKY_NUMBER= "key_lucky"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private fun setOneTimeWorkRequest() {
        // Worker์— ์ „๋‹ฌํ•  Data ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
        val inputData: Data = Data
            .Builder()
            .putInt(KEY_LUCKY_NUMBER, 777)
            .build()

        // WorkRequest ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
        val uploadRequest = OneTimeWorkRequest
            .Builder(UploadWorker::class.java)
            .setInputData(inputData)
            .build()

        // WorkManager ๊ฐ์ฒด์˜ ์ž‘์—… ํ(Job queue)์— WorkRequest ๋“ฑ๋ก
        ...

        // WorkInfo๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๊ฐ์ฒด.
        // WorkManager.getWorkInfoByIdLiveData()๋Š” LiveData<WorkInfo>๋ฅผ ๋ฐ˜ํ™˜.
        ...
        workInfo.observe(this, Observer {
            ...

            if(it.state.name == "SUCCEEDED") {
                val outputData = it.outputData
                Log.i("interfacer_han", "(${this::class.simpleName}) UploadWorker's output: ${outputData.getString(UploadWorker.KEY_UPLOAD_WORKER)}")
            }
        })
    }

    private fun setPeriodicWorkRequest() {
        ...
    }
}

WorkManager์—์„  ์ธ์ž์˜ ์ „๋‹ฌ ๋ฐ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜์„ androidx.work.Data๋กœ ํ•œ๋‹ค. androidx.work.Data๋ฅผ importํ•˜๊ณ  Data ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด Request์— ๋„ฃ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  LiveData.observe() ๋ถ€๋ถ„์„ ์œ„์™€ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค. WorkInfo.outputData๋Š” WorkRequest๊ฐ€ ๋๋‚˜๊ธฐ ์ „์—๋Š” ์•„๋ฌด๋Ÿฐ ๊ฐ’์ด ๋“ค์–ด์žˆ์ง€ ์•Š๋‹ค. ๋”ฐ๋ผ์„œ if๋ฌธ์„ ๋„ฃ์–ด ์ƒํƒœ๋ฅผ ํ™•์ธํ•œ๋‹ค.

 

#2-2 MainActivity - setPeriodicWorkRequest()

...

class MainActivity : AppCompatActivity() {

    companion object {
        const val KEY_LUCKY_NUMBER= "key_lucky"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
    }

    private fun setOneTimeWorkRequest() {
        ...
    }

    private fun setPeriodicWorkRequest() {
        // Worker์— ์ „๋‹ฌํ•  Data ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
        val inputData: Data = Data
            .Builder()
            .putInt(KEY_LUCKY_NUMBER, 777)
            .build()

        // WorkRequest ๊ฐ์ฒด ๋งŒ๋“ค๊ธฐ
        val downloadRequest = PeriodicWorkRequest
            .Builder(DownloadWorker::class.java, 15, TimeUnit.MINUTES) // ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ํ—ˆ์šฉํ•˜๋Š” PeriodicWorkRequest์˜ ์ตœ์†Œ ์ฃผ๊ธฐ๋Š” 15๋ถ„์ด๋‹ค.
            .setInputData(inputData)
            .build()

        // WorkManager ๊ฐ์ฒด์˜ ์ž‘์—… ํ(Job queue)์— WorkRequest ๋“ฑ๋ก
        ...

        // WorkInfo๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด์€ ๊ฐ์ฒด.
        // WorkManager.getWorkInfoByIdLiveData()๋Š” LiveData<WorkInfo>๋ฅผ ๋ฐ˜ํ™˜.
        ...
        workInfo.observe(this, Observer {
            ...

            // ์ด if๋ฌธ ์†์˜ ์ฝ”๋“œ๋Š” ์˜์›ํžˆ ์‹คํ–‰๋˜์ง€ ๋ชปํ•œ๋‹ค.
            if(it.state.name == "SUCCEEDED") {
                val outputData = it.outputData
                Log.i("interfacer_han", "(${this::class.simpleName}) DownloadWorker's output: ${outputData.getString(DownloadWorker.KEY_DOWNLOAD_WORKER)}")
            }
        })
    }
}

#2-1๊ณผ ๊ฐ™์€ ๋งฅ๋ฝ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค. ํ•˜์ง€๋งŒ, #2-1์—์„œ์™€๋Š” ๋‹ฌ๋ฆฌ setPeriodicWorkRequest()์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›์„ ์ˆ˜ ์—†๋‹ค. ์™œ๋ƒํ•˜๋ฉด PeriodicWorkRequest๋Š” ๋๋‚˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค (์ด ๊ฒŒ์‹œ๊ธ€์˜ #4-3 ์ฐธ์กฐ). WorkInfo.outputData๋Š” WorkRequest๊ฐ€ ๋๋‚˜๊ธฐ ์ „์—๋Š” ์•„๋ฌด๋Ÿฐ ๊ฐ’์ด ๋“ค์–ด์žˆ์ง€ ์•Š๋‹ค. ๋”ฐ๋ผ์„œ WorkInfo.outputData๋Š” ํ•ญ์ƒ ๋น„์–ด์žˆ๊ฒŒ ๋œ๋‹ค. ๊ฒฐ๋ก ์ ์œผ๋กœ PeriodicWorkRequest๋กœ๋ถ€ํ„ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›์„ ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ํ•ด๋‹น Request์— ๋“ค์–ด์žˆ๋Š” Worker์—์„œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ์— ๊ฐ’์„ ๋„ฃ๋Š” ์‹์œผ๋กœ ์šฐํšŒํ•ด์•ผ ํ•œ๋‹ค.

 

#2-3 UploadWorker.kt

// package com.example.argumentsandreturn

import android.content.Context
import android.util.Log
import androidx.work.Data
import androidx.work.Worker
import androidx.work.WorkerParameters
import java.text.SimpleDateFormat
import java.util.Date

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

    companion object {
        const val KEY_UPLOAD_WORKER = "key_upload_worker"
    }

    override fun doWork(): Result {
        try {
            Log.i(...)

            val inputtedData = inputData.getInt(MainActivity.KEY_LUCKY_NUMBER, -1)
            Log.i(...)

            for (i in 0..100) {
                ...
            }

            val outputData = Data
                .Builder()
                .putString(KEY_UPLOAD_WORKER, "Hello, MainActivity! I'm UploadWorker")
                .build()

            Log.i(...)
            return Result.success(outputData)

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

    ...
}

#2-1์™€ ๋ฐฉํ–ฅ๋งŒ ๋ฐ˜๋Œ€๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

 

#2-4 DownloadWorker.kt

...

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

    companion object {
        const val KEY_DOWNLOAD_WORKER = "key_download_worker"
    }

    override fun doWork(): Result {
        try {
            ...

            val outputData = Data
                .Builder()
                .putString(KEY_DOWNLOAD_WORKER, "Hello, MainActivity! I'm DownloadWorker.")
                .build()

            ...
            return Result.success(outputData)

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

    ...
}

์ƒ์ˆ˜ ๋ถ€๋ถ„๊ณผ putString() ๋ถ€๋ถ„์„ ์ œ์™ธํ•˜๊ณ , #2-3๊ณผ ์™„์ „ํžˆ ๋™์ผํ•˜๊ฒŒ ์ˆ˜์ •ํ•œ๋‹ค.

 

#3 ์ž‘๋™ ํ™•์ธ

#3-1 'One Time Request' ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ์˜ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€

๋”๋ณด๊ธฐ
(MainActivity) UploadWorker's state: ENQUEUED
(UploadWorker) Started at 2024/06/17 08:31:33
(UploadWorker) Inputted data: 777
(UploadWorker) Progress: 0/100
(UploadWorker) Progress: 1/100
(UploadWorker) Progress: 2/100
(UploadWorker) Progress: 3/100
(UploadWorker) Progress: 4/100
(UploadWorker) Progress: 5/100
(UploadWorker) Progress: 6/100
(UploadWorker) Progress: 7/100
(UploadWorker) Progress: 8/100
(UploadWorker) Progress: 9/100
(UploadWorker) Progress: 10/100
(UploadWorker) Progress: 11/100
(UploadWorker) Progress: 12/100
(UploadWorker) Progress: 13/100
(MainActivity) UploadWorker's state: RUNNING
(UploadWorker) Progress: 14/100
(UploadWorker) Progress: 15/100
(UploadWorker) Progress: 16/100
(UploadWorker) Progress: 17/100
(UploadWorker) Progress: 18/100
(UploadWorker) Progress: 19/100
(UploadWorker) Progress: 20/100
(UploadWorker) Progress: 21/100
(UploadWorker) Progress: 22/100
(UploadWorker) Progress: 23/100
(UploadWorker) Progress: 24/100
(UploadWorker) Progress: 25/100
(UploadWorker) Progress: 26/100
(UploadWorker) Progress: 27/100
(UploadWorker) Progress: 28/100
(UploadWorker) Progress: 29/100
(UploadWorker) Progress: 30/100
(UploadWorker) Progress: 31/100
(UploadWorker) Progress: 32/100
(UploadWorker) Progress: 33/100
(UploadWorker) Progress: 34/100
(UploadWorker) Progress: 35/100
(UploadWorker) Progress: 36/100
(UploadWorker) Progress: 37/100
(UploadWorker) Progress: 38/100
(UploadWorker) Progress: 39/100
(UploadWorker) Progress: 40/100
(UploadWorker) Progress: 41/100
(UploadWorker) Progress: 42/100
(UploadWorker) Progress: 43/100
(UploadWorker) Progress: 44/100
(UploadWorker) Progress: 45/100
(UploadWorker) Progress: 46/100
(UploadWorker) Progress: 47/100
(UploadWorker) Progress: 48/100
(UploadWorker) Progress: 49/100
(UploadWorker) Progress: 50/100
(UploadWorker) Progress: 51/100
(UploadWorker) Progress: 52/100
(UploadWorker) Progress: 53/100
(UploadWorker) Progress: 54/100
(UploadWorker) Progress: 55/100
(UploadWorker) Progress: 56/100
(UploadWorker) Progress: 57/100
(UploadWorker) Progress: 58/100
(UploadWorker) Progress: 59/100
(UploadWorker) Progress: 60/100
(UploadWorker) Progress: 61/100
(UploadWorker) Progress: 62/100
(UploadWorker) Progress: 63/100
(UploadWorker) Progress: 64/100
(UploadWorker) Progress: 65/100
(UploadWorker) Progress: 66/100
(UploadWorker) Progress: 67/100
(UploadWorker) Progress: 68/100
(UploadWorker) Progress: 69/100
(UploadWorker) Progress: 70/100
(UploadWorker) Progress: 71/100
(UploadWorker) Progress: 72/100
(UploadWorker) Progress: 73/100
(UploadWorker) Progress: 74/100
(UploadWorker) Progress: 75/100
(UploadWorker) Progress: 76/100
(UploadWorker) Progress: 77/100
(UploadWorker) Progress: 78/100
(UploadWorker) Progress: 79/100
(UploadWorker) Progress: 80/100
(UploadWorker) Progress: 81/100
(UploadWorker) Progress: 82/100
(UploadWorker) Progress: 83/100
(UploadWorker) Progress: 84/100
(UploadWorker) Progress: 85/100
(UploadWorker) Progress: 86/100
(UploadWorker) Progress: 87/100
(UploadWorker) Progress: 88/100
(UploadWorker) Progress: 89/100
(UploadWorker) Progress: 90/100
(UploadWorker) Progress: 91/100
(UploadWorker) Progress: 92/100
(UploadWorker) Progress: 93/100
(UploadWorker) Progress: 94/100
(UploadWorker) Progress: 95/100
(UploadWorker) Progress: 96/100
(UploadWorker) Progress: 97/100
(UploadWorker) Progress: 98/100
(UploadWorker) Progress: 99/100
(UploadWorker) Progress: 100/100
(UploadWorker) Finished at 2024/06/17 08:31:33
(MainActivity) UploadWorker's state: SUCCEEDED
(MainActivity) UploadWorker's output: Hello, MainActivity! I'm UploadWorker

 

 

#3-2 'Periodic Request' ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ์˜ ๋กœ๊ทธ ๋ฉ”์‹œ์ง€

๋”๋ณด๊ธฐ
(MainActivity) DownloadWorker's state: ENQUEUED
(DownloadWorker) Started at 2024/06/17 08:33:28
(DownloadWorker) Inputted data: 777
(DownloadWorker) Progress: 0/100
(DownloadWorker) Progress: 1/100
(DownloadWorker) Progress: 2/100
(DownloadWorker) Progress: 3/100
(DownloadWorker) Progress: 4/100
(DownloadWorker) Progress: 5/100
(DownloadWorker) Progress: 6/100
(DownloadWorker) Progress: 7/100
(DownloadWorker) Progress: 8/100
(DownloadWorker) Progress: 9/100
(DownloadWorker) Progress: 10/100
(DownloadWorker) Progress: 11/100
(DownloadWorker) Progress: 12/100
(DownloadWorker) Progress: 13/100
(DownloadWorker) Progress: 14/100
(DownloadWorker) Progress: 15/100
(DownloadWorker) Progress: 16/100
(DownloadWorker) Progress: 17/100
(DownloadWorker) Progress: 18/100
(DownloadWorker) Progress: 19/100
(DownloadWorker) Progress: 20/100
(DownloadWorker) Progress: 21/100
(DownloadWorker) Progress: 22/100
(DownloadWorker) Progress: 23/100
(DownloadWorker) Progress: 24/100
(DownloadWorker) Progress: 25/100
(DownloadWorker) Progress: 26/100
(DownloadWorker) Progress: 27/100
(DownloadWorker) Progress: 28/100
(DownloadWorker) Progress: 29/100
(DownloadWorker) Progress: 30/100
(DownloadWorker) Progress: 31/100
(DownloadWorker) Progress: 32/100
(DownloadWorker) Progress: 33/100
(DownloadWorker) Progress: 34/100
(DownloadWorker) Progress: 35/100
(DownloadWorker) Progress: 36/100
(DownloadWorker) Progress: 37/100
(DownloadWorker) Progress: 38/100
(DownloadWorker) Progress: 39/100
(DownloadWorker) Progress: 40/100
(DownloadWorker) Progress: 41/100
(DownloadWorker) Progress: 42/100
(DownloadWorker) Progress: 43/100
(DownloadWorker) Progress: 44/100
(DownloadWorker) Progress: 45/100
(DownloadWorker) Progress: 46/100
(DownloadWorker) Progress: 47/100
(DownloadWorker) Progress: 48/100
(DownloadWorker) Progress: 49/100
(DownloadWorker) Progress: 50/100
(DownloadWorker) Progress: 51/100
(DownloadWorker) Progress: 52/100
(DownloadWorker) Progress: 53/100
(DownloadWorker) Progress: 54/100
(DownloadWorker) Progress: 55/100
(DownloadWorker) Progress: 56/100
(DownloadWorker) Progress: 57/100
(DownloadWorker) Progress: 58/100
(DownloadWorker) Progress: 59/100
(DownloadWorker) Progress: 60/100
(DownloadWorker) Progress: 61/100
(DownloadWorker) Progress: 62/100
(DownloadWorker) Progress: 63/100
(DownloadWorker) Progress: 64/100
(DownloadWorker) Progress: 65/100
(DownloadWorker) Progress: 66/100
(DownloadWorker) Progress: 67/100
(DownloadWorker) Progress: 68/100
(DownloadWorker) Progress: 69/100
(DownloadWorker) Progress: 70/100
(DownloadWorker) Progress: 71/100
(DownloadWorker) Progress: 72/100
(DownloadWorker) Progress: 73/100
(MainActivity) DownloadWorker's state: RUNNING
(DownloadWorker) Progress: 74/100
(DownloadWorker) Progress: 75/100
(DownloadWorker) Progress: 76/100
(DownloadWorker) Progress: 77/100
(DownloadWorker) Progress: 78/100
(DownloadWorker) Progress: 79/100
(DownloadWorker) Progress: 80/100
(DownloadWorker) Progress: 81/100
(DownloadWorker) Progress: 82/100
(DownloadWorker) Progress: 83/100
(DownloadWorker) Progress: 84/100
(DownloadWorker) Progress: 85/100
(DownloadWorker) Progress: 86/100
(DownloadWorker) Progress: 87/100
(DownloadWorker) Progress: 88/100
(DownloadWorker) Progress: 89/100
(DownloadWorker) Progress: 90/100
(DownloadWorker) Progress: 91/100
(DownloadWorker) Progress: 92/100
(DownloadWorker) Progress: 93/100
(DownloadWorker) Progress: 94/100
(DownloadWorker) Progress: 95/100
(DownloadWorker) Progress: 96/100
(DownloadWorker) Progress: 97/100
(DownloadWorker) Progress: 98/100
(DownloadWorker) Progress: 99/100
(DownloadWorker) Progress: 100/100
(DownloadWorker) Finished at 2024/06/17 08:33:28
(MainActivity) DownloadWorker's state: ENQUEUED

์ดํ•˜ ์ƒ๋žต

 

#4 ์š”์•ฝ

๋๋‚˜๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•œ WorkRequest์—๊ฒŒ์„œ๋งŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

 

#5 ์™„์„ฑ๋œ ์•ฑ

 

android-practice/work-manager/ArgumentsAndReturn at master · Kanmanemone/android-practice

Contribute to Kanmanemone/android-practice development by creating an account on GitHub.

github.com