본문 바로가기
2023년 이전/Android

Android - WorkManager (4) -Observing intermediate Worker progress

by JeongUPark 2019. 10. 17.
반응형

이전 글 : 2019/10/17 - [프로그래밍/Android] - Android - WorkManager (3) - Work States and observing work

출처 - Android developer Observing intermediate Worker progress

WorkManager 2.3.0-alpha01은 작업자의 중간 진행 상황을 설정하고 관찰하는 first-class를 추가합니다. 앱이 포 그라운드에있는 동안 Worker가 실행중인 경우 WorkInfo의 LiveData를 반환하는 API를 사용하여이 정보를 사용자에게 표시 할 수도 있습니다.

 

ListenableWorker는 이제 setProgressAsync () API를 지원하므로 중간 진행률을 유지할 수 있습니다. 이러한 API를 통해 개발자는 UI에서 관찰 할 수있는 중간 진행률을 설정할 수 있습니다. Progress는 serializable container of properties 데이터 유형으로 표시됩니다 (입력 및 출력과 유사하며 동일한 제한이 적용됨).

 

진행 정보는 ListenableWorker가 실행되는 동안에 만 관찰 및 업데이트 될 수 있습니다. ListenableWorker가 실행을 완료 한 후 진행률을 설정하려는 시도는 무시됩니다. getWorkInfoBy… () 또는 getWorkInfoBy… LiveData () 메소드 중 하나를 사용하여 진행 정보를 관찰 할 수도 있습니다. 이러한 메소드는 Data를 리턴하는 새로운 getProgress () 메소드가있는 WorkInfo 인스턴스를 리턴합니다.

 

Updating Progress

 

ListenableWorker 또는 Worker를 사용하는 Java 개발자의 경우 setProgressAsync () API는 ListenableFuture <Void>를 반환합니다. 업데이트 프로세스는 데이터베이스에 진행 정보를 저장하는 것을 포함하므로 업데이트 진행은 비동기식입니다. Kotlin에서는 CoroutineWorker 객체의 setProgress () 확장 함수를 사용하여 진행 정보를 업데이트 할 수 있습니다.

 

Observing Progress

진행 정보를 관찰하는 것도 간단합니다. getWorkInfoBy… () 또는 getWorkInfoBy… LiveData () 메소드를 사용하여 WorkInfo에 대한 참조를 얻을 수 있습니다.

 

그럼 위 2가지를 가지고 simple test code를 만들어 보겠습니다.

 

언제나 그렇듯 File->New->New Project에서 Fragment+Viewmodel을 선택해서 project를 생성합니다.

다음 UpdateProgressWorker를 만듭니다.

class UpdateProgressWorker(context: Context, parameters: WorkerParameters) : CoroutineWorker(context, parameters){
    companion object{
        const val Progress = "Progress"
        private const val  delayDuration = 1L
    }

    override suspend fun doWork(): Result {
        val firstUpdate = workDataOf(Progress to 10)
        val lastUpdate = workDataOf(Progress to 100)
        setProgress(firstUpdate)
        delay(delayDuration)
        setProgress(lastUpdate)
        return Result.success()
    }

}

위의 code를 작성할 때 이 글을 따라 오거나 Android developer에 WorkManager를 추가하는 방법을 보고 추가하셨다면 work_version이 2.2.0이 셨을 것입니다. 하지만 위 code에서 setProgress는 2.3.0-alpha01 부터 적용 되므로 work_version을 2.3.0-alpha01으로 변경해야합니다.

 

그리고 MainFragment의 Xml을

<?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/updateprocess_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="Progress Doing"/>
</androidx.constraintlayout.widget.ConstraintLayout>

 하고 MainFragment를

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 updateWorkRequest = OneTimeWorkRequestBuilder<UpdateProgressWorker>()
            .build()

        updateprocess_start_btn.setOnClickListener {
            v ->
            WorkManager.getInstance(context!!).enqueue(updateWorkRequest)
        }
        WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(updateWorkRequest.id)
            .observe(viewLifecycleOwner, Observer {
                workInfo->
                workInfo?.let {
                    val progress = workInfo.progress
                    val value = progress.getInt("Progress",0)
                    Log.d("TEST", "value: $value")
                }
            })
    }
}

 이렇게 작성 후 동작 시키면 log를 통하여 progress 변경을  Observer가 잘 캐치하고 있다는 것을 확인 할 수 있습니다. (실행은 생성한 버튼을 누르면 실행 됩니다.)

(사실 이전 글인 2019/10/16 - [프로그래밍/Android] - Android - WorkManager (2) WorkRequest 에서 이미 Observer를 통하여 doWork의 결과 값을 받는것은 사용 했었습니다. ^^)

반응형