관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[안드로이드] 구글 공식 프로젝트 Sunflower 스터디 (8) Service(WorkManager) 본문

안드로이드/코틀린 & 아키텍처 & Recent

[안드로이드] 구글 공식 프로젝트 Sunflower 스터디 (8) Service(WorkManager)

막무가내막내 2021. 5. 10. 18:30
728x90

 

 

 

[출처 및 참고] 

github.com/android/sunflower

 

android/sunflower

A gardening app illustrating Android development best practices with Android Jetpack. - android/sunflower

github.com

youngest-programming.tistory.com/361

 

[안드로이드] Android Jetpack WorkManager 백그라운드 작업처리 정리

[2021-04-14 업데이트] [먼저 이 모든 코드는 제가 실제 업무에 적용한 프로젝트 코드가 아닌 예제로 만든 것임을 알려드립니다. 그래서 오타가 있을 수도 있습니다. ] [참고] https://developer.android.com/g

youngest-programming.tistory.com

youngest-programming.tistory.com/367

 

[안드로이드] 안드로이드 AlarmManager 와 WorkManager 사용하여 10분전 알림 만들기

[2021-04-14 업데이트] github.com/mtjin/NoMoneyTrip mtjin/NoMoneyTrip SKT 2020 스마트 관광앱 공모전 '무전여행' 앱. Contribute to mtjin/NoMoneyTrip development by creating an account on GitHub. github..

youngest-programming.tistory.com

developer.android.com/topic/libraries/architecture/workmanager?hl=ko

 

WorkManager로 작업 예약  |  Android 개발자  |  Android Developers

WorkManager로 작업 예약  Android Jetpack의 일부 WorkManager는 지연 가능한 비동기 작업을 쉽게 예약할 수 있는 API로, 지연 가능한 비동기 작업은 앱이 종료되거나 기기가 다시 시작되더라도 실행될 것

developer.android.com

developer.android.com/topic/libraries/architecture/workmanager/advanced/coroutineworker?hl=ko

 

CoroutineWorker의 스레딩  |  Android 개발자  |  Android Developers

WorkManager는 Kotlin 사용자에게 코루틴을 위한 최고 수준의 지원을 제공합니다. 시작하려면 gradle 파일에 work-runtime-ktx를 포함해야 합니다. Worker를 확장하는 대신 doWork()의 정지 버전인 CoroutineWorker를

developer.android.com

 

 

[Service - Jetpack WorkManager]

이전 챕터에서 Model - Repository 에 대해 보았는데 이번에는 Service 관련 클래스에 대해 살펴보려고 한다. 이 프로젝트에서는 관련된게 Jetpack 컴포넌트의 WorkManager 만 있다.

 

WorkManager에 대해 간략히 설명하자면, 지연 가능한 비동기 작업을 쉽게 예약할 수 있는 API로, 지연 가능한 비동기 작업은 앱이 종료되거나 기기가 다시 시작되더라도 실행될 것으로 예상되는 작업이다.


[SeedDatabaseWorker]

class SeedDatabaseWorker(
    context: Context,
    workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
    override suspend fun doWork(): Result = coroutineScope {
        try {
            applicationContext.assets.open(PLANT_DATA_FILENAME).use { inputStream ->
                JsonReader(inputStream.reader()).use { jsonReader ->
                    val plantType = object : TypeToken<List<Plant>>() {}.type
                    val plantList: List<Plant> = Gson().fromJson(jsonReader, plantType)

                    val database = AppDatabase.getInstance(applicationContext)
                    database.plantDao().insertAll(plantList)

                    Result.success()
                }
            }
        } catch (ex: Exception) {
            Log.e(TAG, "Error seeding database", ex)
            Result.failure()
        }
    }

    companion object {
        private const val TAG = "SeedDatabaseWorker"
    }
}

 

[사용한 곳]

@Database(entities = [GardenPlanting::class, Plant::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun gardenPlantingDao(): GardenPlantingDao
    abstract fun plantDao(): PlantDao

    companion object {

        // For Singleton instantiation
        @Volatile private var instance: AppDatabase? = null

        fun getInstance(context: Context): AppDatabase {
            return instance ?: synchronized(this) {
                instance ?: buildDatabase(context).also { instance = it }
            }
        }

        // Create and pre-populate the database. See this article for more details:
        // https://medium.com/google-developers/7-pro-tips-for-room-fbadea4bfbd1#4785
        private fun buildDatabase(context: Context): AppDatabase {
            return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                .addCallback(
                    object : RoomDatabase.Callback() {
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                            val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
                            WorkManager.getInstance(context).enqueue(request)
                        }
                    }
                )
                .build()
        }
    }
}

 

[assets]

 

 

/assets
[
  {
    "plantId": "malus-pumila",
    "name": "Apple",
    "description": "An apple is a sweet, edible fruit produced by an apple tree (Malus pumila). Apple trees are cultivated worldwide, and are the most widely grown species in the genus Malus. The tree originated in Central Asia, where its wild ancestor, Malus sieversii, is still found today. Apples have been grown for thousands of years in Asia and Europe, and were brought to North America by European colonists. Apples have religious and mythological significance in many cultures, including Norse, Greek and European Christian traditions.<br><br>Apple trees are large if grown from seed. Generally apple cultivars are propagated by grafting onto rootstocks, which control the size of the resulting tree. There are more than 7,500 known cultivars of apples, resulting in a range of desired characteristics. Different cultivars are bred for various tastes and uses, including cooking, eating raw and cider production. Trees and fruit are prone to a number of fungal, bacterial and pest problems, which can be controlled by a number of organic and non-organic means. In 2010, the fruit's genome was sequenced as part of research on disease control and selective breeding in apple production.<br><br>Worldwide production of apples in 2014 was 84.6 million tonnes, with China accounting for 48% of the total.<br><br>(From <a href=\"https://en.wikipedia.org/wiki/Apple\">Wikipedia</a>)",
    "growZoneNumber": 3,
    "wateringInterval": 30,
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/5/55/Apple_orchard_in_Tasmania.jpg"
  },
  {
    "plantId": "beta-vulgaris",
    "name": "Beet",
    "description": "The beetroot is the taproot portion of the beet plant, usually known in North America as the beet and also known as the table beet, garden beet, red beet, or golden beet. It is one of several of the cultivated varieties of Beta vulgaris grown for their edible taproots and their leaves (called beet greens). These varieties have been classified as B. vulgaris subsp. vulgaris Conditiva Group.<br><br>Other than as a food, beets have use as a food colouring and as a medicinal plant. Many beet products are made from other Beta vulgaris varieties, particularly sugar beet.<br><br>(From <a href=\"https://en.wikipedia.org/wiki/Beetroot\">Wikipedia</a>)",
    "growZoneNumber": 2,
    "wateringInterval": 7,
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/2/29/Beetroot_jm26647.jpg"
  },

 

SeedDatabaseWorker는 비동기 백그라운드로 assets에 있는 json 데이터를 데이터베이스에 저장하는 작업을 위해 한 번만 실행되게 사용되었다. 코드를 보면 알겠지만 doWork()에서 작업이 성공시 Result.success() 실패시 Result.failure()가 호출되게 된다. 그리고 여기서는 파라미터를 전달받는 작업은 없어서 workParams는 사용되지 않았다.

 

SeedDatabaseWorker 에서 평소 내가 사용했던 WorkManager와 다르게 Worker 가 아닌 CoroutineWorker를 상속받고 있다는 특징이 있었다. 

 

이를 사용하기 위해서는  ktx 버전 디펜던시를 추가해주어야한다. 

dependencies {
  def work_version = "2.5.0"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"

    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"

 

 

CoroutineWorker에 대해 알아보면 WorkManager에서 Kotlin 사용자에게 코루틴을 위한 지원을 제공한 것이다. Worker를 확장하는 대신 doWork()의 suspend 버전인 CoroutineWorker를 상속해야 한다. 예를 들어 간단한 CoroutineWorker를 빌드하여 일부 네트워크 작업을 실행하려면 다음과 같이 하면 된다.

 

CoroutineWorker.doWork()는 suspend 함수이다. Worker와 달리 이 코드는 Configuration에 지정된 Executor에서 실행되지 않는다. 대신 Dispatchers.Default 기본값으로 지정된다. 고유의 CoroutineContext를 제공하여 이를 맞춤설정할 수도 있다. 

(여기서는 applicationContext를 사용하였다.)

 

CoroutineWorker는 코루틴을 취소하고 취소 신호를 전파하여 자동으로 중지를 처리한다. 작업 중지를 처리하기 위해 특별히 해야 할 일은 없다.

 

CoroutineWorker에 대한 자세한 내용은 developer.android.com/topic/libraries/architecture/workmanager/advanced/coroutineworker?hl=ko에서 볼 수 있다.

 

 

 

Jetpack WorkManager에 대해서는 예전에 포스팅에서 살짝다뤄본적이 있다. 

youngest-programming.tistory.com/361

youngest-programming.tistory.com/367

추가로 WorkManager는 공식문서를 보면 설명이 잘 되어 있으므로 모르거나 필요한 기능을 갖다가 사용하면 된다.

developer.android.com/topic/libraries/architecture/workmanager?hl=ko 

 

WorkManager로 작업 예약  |  Android 개발자  |  Android Developers

WorkManager로 작업 예약  Android Jetpack의 일부 WorkManager는 지연 가능한 비동기 작업을 쉽게 예약할 수 있는 API로, 지연 가능한 비동기 작업은 앱이 종료되거나 기기가 다시 시작되더라도 실행될 것

developer.android.com

 

 

댓글과 공감은 큰 힘이 됩니다. 감사합니다. !! 

728x90
Comments