출처 - Android Developer WorkManager 페이지
Android Oreo 부터 긴 작업의 백그라운드 서비스와 브로드캐스트가 제한이 되었습니다. (자세한 사항은 여기서 확인해 주세요) 그래서 Android Oreo 이후 백그라운드 서비스 또는 브로드캐스트를 사용하기 위해서는 WorkManager를 사용하게 되었습니다.
즉 WorkManager는 즉시 실행하지 않아도되며, 앱이 종료되거나 장치가 다시 시작 되더라도 안정적으로 실행해야하는 작업을위한 것입니다. 예를 들어 이미지를 서버에 업로드 해야 하거나, 데이터를 분석하고 이를 데이터베이스에 저장해야 하는 작업에는 WorkManager 를 사용하는것이 좋습니다.
그러나 사용자가 현재 보고있는 UI 를 빠르게 변경해야 하는 작업이나 물건 구입 과정에서의 결제 진행 등 즉시 처리해야 하는 작업은 WorkManager 를 사용하지 않는것이 좋습니다.
WorkManager 의 작업은 반드시 실행되지만 그 처리가 상황에 따라 지연 되거나 도중에 중단될 경우 다시 실행 될수 있다는 것을 꼭 기억해야 합니다. 적절한 상황에서, WorkManager 는 AlarmManager 나 JobScheduler, JobDispather 를 대체하는 훌륭한 백그라운드 작업 처리 방법입니다
(WorkManager를 써야하는 사황에 대해서는 Android Developer에 Guide to background processing에서 자세히 확인 하실 수 있습니다.)
그럼 간단한 사용 방법을 확인해 보겠습니다.
우선 File -> New -> New Project를 선택하고 Fragment+ViewModel을 선택하여 프로젝트를 만듭니다.
WorkManager를 프로젝트에 추가 합니다. 추가 방법은
Project build.gradle에 다음과 같이 Google Maven repository가 추가 되있어야 하고(프로젝트를 만들면 보통은 추가되어 있을 것 입니다.)
allprojects {
repositories {
google()
....
}
}
Module build.gradle에 다음 라이프러리들을 추가합니다.
dependencies {
def work_version = "2.2.0"
// (Java only)
implementation "androidx.work:work-runtime:$work_version"
// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
// optional - RxJava2 support
implementation "androidx.work:work-rxjava2:$work_version"
// optional - GCMNetworkManager support
implementation "androidx.work:work-gcm:$work_version"
// optional - Test helpers
androidTestImplementation "androidx.work:work-testing:$work_version"
}
Background task를 만들 때는 work class를 활용하여 만듭니다. 그리고 그 동작은 dowork() Method에서하며 결과를 반환 해야 합니다. 즉 작업의 단위를 결정합니다. 그리고 그 결과를 반환하는데, Result.failure(), Result.success(), Result.retry()가 있습니다.
그럼 Background task를 만들기 위해 MyWorker라는 class를 만들고 Worker class를 확장합니다. 그리고 dowork() Method를 overrride 합니다.
class MyWorker (appContext : Context, workerParams: WorkerParameters) : Worker(appContext,workerParams){
override fun doWork(): Result {
var count = 0
var doCounting = true
while (doCounting){
Log.d("TEST","now Count : ${++count}" )
if(count == 60){
doCounting = false
}
Thread.sleep(1000)
}
return Result.success()
}
}
위의 doWork에 작성된 동작은 1초마다 count를 하고 그 값을 console Log로 표출 합니다.
그리고 MainFragment를 다음과 같이 작성합니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.MainFragment">
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MainFragment"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/workmanager_start_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Doing"/>
</androidx.constraintlayout.widget.ConstraintLayout>
class MainFragment : Fragment() {
companion object {
fun newInstance() = MainFragment()
}
private lateinit var viewModel: MainViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.main_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>().build()
workmanager_start_btn.setOnClickListener {
WorkManager.getInstance(context!!).enqueue(myWorkRequest)
}
}
}
Woker가 작업 단위를 정의한다면, WorkRequest는 작업 실행 및 시기를 정합니다. 한번 작업은 OneTimeWorkRequest로 주기적인 작업은 PeriodicWorkRequest을 사용합니다.
여기서 저는 한번의 작업을 위해 OneTimeWorkRequest를 만들었습니다. OneTimeWorkRequest는 위의 code 처럼 OneTimeWorkRequestBuilder를 통하여 만들어 수 있습니다. (OneTimeWorkRequestBuilder 는 jvmTarget 설정이 필요 합니다. 그러므로 Module build.gradle의 android 블럭 안에 다음과 같이 추가합니다.)
android{
.....
kotlinOptions {
jvmTarget = "1.8"
}
}
그리고 이렇게 생성된 WorkRequest를 WorkManager에 enqueue 하면 동작 합니다. 작업자가 실행되는 정확한 시간은 WorkRequest에 사용 된 제약 조건과 시스템 최적화에 따라 다릅니다.
그럼 작업 한 App을 실행해 보면
이런 결과를 볼 수 있고 doing 버튼을 누르면
Log를 볼 수 있습니다. 이 로그는 App을 Background 상태에 두어도 계속 동작합니다.(단, App을 완전히 종료 시키면 멈춥니다.)
'2023년 이전 > Android' 카테고리의 다른 글
Android - WorkManager (3) - Work States and observing work (0) | 2019.10.17 |
---|---|
Android - WorkManager (2) WorkRequest (0) | 2019.10.16 |
Android -LiveData (0) | 2019.10.15 |
Android - ViewModel (0) | 2019.10.15 |
custom 숫자 키 입력 - 보안 숫자 keyboard (0) | 2019.09.06 |