워크매니져는 앱의 상태(포그라운드,백그라운드)와 무관하게 진행되어야 하는 작업들을 관리해주며 안드로이드가 작업을 중지시켰을때 재시작을 하게 해준다. 그리고 제한사항을 통해 배터리와 관계를 통해 백그라운드에서의 활동을 좀 더 다루기 쉽게?(유용하게?) 해줌.
백그라운드작업은 디바이스의 제한된 리소스를 사용하고, 배터리를 잡아먹는다. 그래서 폰의 배터리가 빨리달거나 하는 불편한 상황을 겪을 수 있음.
백그라운드에서 진행될 작업이 있는가부터 고민을 해봐야한다고 함. 그리고 그 작업이 지연이 가능한 작업인가? 고민해봐야함.
그럼 SunFlower에서는 어떻게 사용하고 있는가를 봐보자
1. Database를 만들떄 work를 사용함
@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()
}
}
}
여기서 작동하는건 데이터베이스가 만들어지면 데이터베이스에다가 기본적인 Plant데이터를 넣는 과정이다.
이렇게 최초로 데이터베이스가 만들어 지게되면 Work가 작동하도록 만들기 위해서 addCallback 함수를 사용하여 만들어 주는데 onCreate를 오버라이드 해주면서 다음과 같은 work를 실행시킨다.
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"
}
}
이 작업을 통해서 최초의 데이터베이스에는 Plant리스트가 들어가게 된다! 하나씩 분석해보자
Work가 작동하는 과정은 이렇다.
1) Worker에 work를 지정 ->
2) WorkRequest작성(언제 어떻게 Worker가 작동되는가) ->
3) 시스템에 WorkRequest 제출(enqueue사용)
(1) Worker
WorkManager의 관리를 받으며 work를 백그라운드에서 실행하는 일꾼?임
doWork를 이용하여 지정된 백그라운드 스레드에서 작동하며 작동된 후에 끝이 나면 더이상 사용되지 않는다(doWork함수는 한 woker당 한번만 작동된다.) 혹시 비동기적인 작업을 원한다면 리스너를 통한 작업을 해야함. worker은 10분의 작업 시간 한계가 있고 완료되지 않으면 실패로 뜨게 된다.
(2) CoroutineWorker
코루틴을 지원하는 Worker로 suspend fun으로 doWork를 지원함. 이 함수는 Excutor에서 작동하지 않고 Dispather.IO에서 작동한다는데 쓰레드에 대해서 나중에 좀 자세히 알아보아야 겠다.
그래서 위의 SeedDatabaseWorker는 코루틴 스코프에서 진행되며 Database에 기본적인 데이터를 Dao를 통해 집어넣는다. 이러한 과정이 성공햇는지 실패했는지에 대해서 Result.success()나 Result.failure()를 통해서 알려준다.
위의 예제는 CoroutineWorker을 사용하여 Worker를 정의해 주었다.
그리고
val request = OneTimeWorkRequestBuilder<SeedDatabaseWorker>().build()
위를 통해서 request를 작성하고
WorkManager.getInstance(context).enqueue(request)
워크 매니져에 등록해준다.
한번 사용해봄
doojuns-ordinary.tistory.com/48
2. workmanager 사용해보자
workManager을 사용해서 데이터를 넣어보자 앞서 만든 Database를 조금 바꿔서 fun getDatabase( context: Context, ):MsgDatabase { if(INSTANCE ==null){ val instance = Room.databaseBuilder( context.applica..
doojuns-ordinary.tistory.com
'안드로이드 jetpack > sunflower' 카테고리의 다른 글
6.liveData를 사용해 보자(Viewmodel 적용기) (0) | 2021.05.04 |
---|---|
4. Paging, PagingAdapter (0) | 2021.05.02 |
3.recyclerview(ListAdapter) (0) | 2021.05.02 |
2.sunflower분석 ( hilt) (0) | 2021.04.29 |
1. DI 종속성 주입 (sunflower 분석 ,hilt, dagger) (0) | 2021.04.29 |