Setup and starter code walkthrough
Step 1: 스타터 앱 다운로드받고 실행하기
github.com/google-developer-training/android-kotlin-fundamentals-apps/tree/master/DevBytesRepository
Step 2: 코드 살펴보기
Concept: WorkManager
Add the WorkManager dependency
build.gradle (Module:app)
dependencies {
...
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
}
Create a background worker
Step 1: worker 생성하기
work/RefreshDataWorker.kt
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
return Result.success()
}
}
suspending function은 나중에 중단되고 재개될 수 있는 함수이다. suspending function은 오랫동안 실행되는 작업을 수행할 수 있고 메인 스레드가 블락되지 않고 완료되기를 기다릴 수 있다.
Step 2: doWork() 구현하기
RefreshDataWorker.kt
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
return Result.success()
}
}
Define a periodic WorkRequest
Note: periodic work의 최소 간격은 15분이다. periodic work의 제약 중 하나로 periodic work은 초기 delay를 가질 수 없다.
Step 1: 반복적인 작업 설정하기
DevByteApplication.kt
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
}
Step 2: WorkManager로 WorkRequest 스케줄링하기
RefreshDataWorker.kt
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
DevByteApplication.kt
class DevByteApplication : Application() {
private val applicationScope = CoroutineScope(Dispatchers.Default)
/**
* onCreate is called before the first screen is shown to the user.
*
* Use it to setup any background tasks, running expensive setup operations in a background
* thread to avoid delaying app start.
*/
override fun onCreate() {
super.onCreate()
delayedInit()
}
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
}
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
}
같은 이름의 보류된(끝나지 않은) 작업이 존재하면 ExistingPeriodicWorkPolicy.KEEP 매개변수가 WorkManager가 이전의 periodic work를 유지하고 요청된 새로운 작업을 폐기하도록 한다.
Best Practice: onCreate() 메서드는 메인 스레드에서 실행된다. onCreate()에서 long-running operation을 수행한느 것은 UI 스레드를 블락할 수 있고 앱 로딩 딜레이를 발생시킬 수 있다. 이 문제를 피하기 위해 메인 스레드에서 벗어나 코루틴 안에서 Timber 초기화와 WorkManager 스케줄링 같은 task를 수행한다.
Step 3: (Optional) 최소 간격으로 WorkRequest 스케줄링하기
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
Add constraints
Step 1: Constraint 객체를 추가하고 제약 하나를 설정하기
DevByteApplication.kt
private fun setupRecurringWork() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
...
}
Step 2: 앱을 실행하고 로그 확인하기
Step 3: 더 많은 제약 추가하기
DevByteApplication.kt
private fun setupRecurringWork() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Timber.d("Periodic Work request for sync is scheduled")
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
}
Homework
Q1. 2 / Q2. 1 / Q3. 1
Quiz
1. 3 / 2. 1 / 3. 2 / 4. 1 / 5. 2, 3 / 6. 1 / 7. 1
'안드로이드 Android > Android Study Jams' 카테고리의 다른 글
9. Repository and workManager - Add a Repository (0) | 2021.01.29 |
---|---|
8. Connect to the internet - Filter and create views with internet data (0) | 2021.01.28 |
8. Connect to the internet - Load and display images from the internet (0) | 2021.01.28 |
8. Connect to the internet - Get data from the internet (0) | 2021.01.28 |
7. Databases and RecyclerView - RecyclerView Fundamentals (0) | 2021.01.21 |