Worker의 스레딩

Worker를 사용하면 WorkManager는 자동으로 백그라운드 스레드에서 Worker.doWork()를 호출합니다. 백그라운드 스레드의 출처는 WorkManager의 Configuration에 명시된 Executor입니다. 기본적으로 WorkManager에서 개발자를 위해 Executor를 설정하지만, 개발자가 직접 맞춤설정할 수도 있습니다. 예를 들어 앱에서 기존 백그라운드 Executor를 공유하거나 단일 스레드 Executor를 만들어 모든 백그라운드 작업이 순차적으로 실행되도록 하거나 맞춤 Executor를 지정하면 됩니다. Executor를 맞춤설정하려면 WorkManager를 직접 초기화해야 합니다.

WorkManager를 직접 구성할 때 다음과 같이 Executor를 지정하세요.

Kotlin

WorkManager.initialize(
    context,
    Configuration.Builder()
         // Uses a fixed thread pool of size 8 threads.
        .setExecutor(Executors.newFixedThreadPool(8))
        .build())

Java

WorkManager.initialize(
    context,
    new Configuration.Builder()
        .setExecutor(Executors.newFixedThreadPool(8))
        .build());

다음은 웹페이지 콘텐츠를 100번 다운로드하는 간단한 Worker의 예입니다.

Kotlin

class DownloadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): ListenableWorker.Result {
        repeat(100) {
            try {
                downloadSynchronously("https://www.google.com")
            } catch (e: IOException) {
                return ListenableWorker.Result.failure()
            }
        }

        return ListenableWorker.Result.success()
    }
}

Java

public class DownloadWorker extends Worker {

    public DownloadWorker(Context context, WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        for (int i = 0; i < 100; i++) {
            try {
                downloadSynchronously("https://www.google.com");
            } catch (IOException e) {
                return Result.failure();
            }
        }

        return Result.success();
    }

}

Worker.doWork()는 동기 호출입니다. 즉, 전체 백그라운드 작업을 차단 방식으로 실행하고 메서드가 종료될 때까지 작업을 완료하도록 요구됩니다. doWork()에서 비동기 API를 호출하고 Result를 반환하면 콜백이 제대로 작동하지 않을 수 있습니다. 이런 상황에서는 ListenableWorker를 사용하는 것이 좋습니다(ListenableWorker의 스레딩 참고).

현재 실행 중인 Worker어떤 이유로든 중지되면 Worker.onStopped() 호출을 수신합니다. 필요한 경우 이 메서드를 재정의하거나 Worker.isStopped()를 호출하여 코드에 체크포인트를 설정하고 리소스를 해제합니다. 위의 예에서는 Worker가 중지되었을 때 항목을 다운로드하는 루프 안에 있을 가능성이 있으며 이로 인해 중지되었음에도 계속 실행될 수도 있습니다. 이 동작을 최적화하려면 다음과 같이 하면 됩니다.

Kotlin

class DownloadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): ListenableWorker.Result {
        repeat(100) {
            if (isStopped) {
                break
            }

            try {
                downloadSynchronously("https://www.google.com")
            } catch (e: IOException) {
                return ListenableWorker.Result.failure()
            }

        }

        return ListenableWorker.Result.success()
    }
}

Java

public class DownloadWorker extends Worker {

    public DownloadWorker(Context context, WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        for (int i = 0; i < 100; ++i) {
            if (isStopped()) {
                break;
            }

            try {
                downloadSynchronously("https://www.google.com");
            } catch (IOException e) {
                return Result.failure();
            }
        }

        return Result.success();
    }
}

일단 Worker가 중지되면 Result는 무시되므로 Worker.doWork()에서 무엇을 반환하는지는 중요하지 않습니다.