Panduan memulai mencakup cara membuat WorkRequest
sederhana
dan mengantrekannya.
Dalam panduan ini, Anda akan mempelajari cara menentukan dan menyesuaikan objek WorkRequest
untuk menangani kasus penggunaan umum, seperti cara:
- Menjadwalkan pekerjaan satu kali dan berulang
- Menyetel batasan kerja, seperti perlu menggunakan Wi-Fi atau mengisi daya untuk melakukan pekerjaan
- Menjamin penundaan minimum dalam eksekusi pekerjaan
- Menetapkan strategi percobaan ulang dan back-off
- Meneruskan input data ke pekerjaan
- Mengelompokkan pekerjaan yang saling berkaitan menggunakan tag
Ringkasan
Pekerjaan ditentukan di WorkManager melalui WorkRequest
. Untuk
menjadwalkan pekerjaan apa pun dengan WorkManager, terlebih dahulu Anda harus membuat objek
WorkRequest
, lalu mengantrekannya.
Kotlin
val myWorkRequest = ... WorkManager.getInstance(myContext).enqueue(myWorkRequest)
Java
WorkRequest myWorkRequest = ... WorkManager.getInstance(myContext).enqueue(myWorkRequest);
Objek WorkRequest berisi semua informasi yang diperlukan oleh WorkManager untuk menjadwalkan dan menjalankan pekerjaan Anda. Ini mencakup batasan yang harus dipenuhi agar tugas dapat dijalankan, penjadwalan informasi seperti penundaan atau interval berulang, konfigurasi percobaan ulang, dan mungkin termasuk menginput data jika tugas membutuhkannya.
WorkRequest
adalah class dasar abstrak. Ada dua
implementasi turunan dari class ini yang dapat Anda gunakan untuk membuat permintaan,
OneTimeWorkRequest
dan PeriodicWorkRequest
.
Sesuai dengan namanya, OneTimeWorkRequest
berguna untuk menjadwalkan
tugas yang tidak berulang, sementara PeriodicWorkRequest
lebih cocok untuk
menjadwalkan tugas yang berulang pada beberapa interval.
Menjadwalkan pekerjaan satu kali
Untuk tugas sederhana, yang tidak memerlukan konfigurasi tambahan, gunakan
metode statis from
:
Kotlin
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
Java
WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);
Untuk tugas yang lebih kompleks, Anda dapat menggunakan builder:
Kotlin
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() // Additional configuration .build()
Java
WorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) // Additional configuration .build();
Menjadwalkan pekerjaan yang diprioritaskan
WorkManager 2.7.0 memperkenalkan konsep pekerjaan yang diprioritaskan. Hal ini memungkinkan WorkManager mengeksekusi pekerjaan penting sekaligus memberi sistem kontrol yang lebih baik untuk akses ke resource.
Pekerjaan yang diprioritaskan menjadi penting karena karakteristik berikut:
- Tingkat kepentingan: Tugas yang diprioritaskan cocok dengan tugas yang penting bagi pengguna atau yang dimulai oleh pengguna.
- Kecepatan: Pekerjaan yang diprioritaskan paling sesuai dengan tugas singkat yang dimulai segera dan selesai dalam beberapa menit.
- Kuota: Kuota tingkat sistem yang membatasi waktu eksekusi latar depan menentukan apakah tugas yang diprioritaskan dapat dimulai.
- Pengelolaan Daya: Pembatasan pengelolaan daya, seperti fitur Penghemat Baterai dan Istirahatkan, cenderung tidak memengaruhi tugas yang diprioritaskan.
- Latensi: Sistem langsung mengeksekusi tugas yang diprioritaskan, asalkan beban kerja sistem saat ini memungkinkannya. Ini berarti sistem peka terhadap latensi dan tidak dapat dijadwalkan untuk eksekusi berikutnya.
Kasus penggunaan potensial untuk pekerjaan yang diprioritaskan mungkin berada dalam aplikasi chat saat pengguna ingin mengirim pesan atau gambar terlampir. Demikian pula, aplikasi yang menangani alur pembayaran atau langganan mungkin juga ingin menggunakan tugas yang diprioritaskan. Hal ini karena tugas tersebut penting bagi pengguna, dieksekusi dengan cepat di latar belakang, harus segera dimulai, dan harus terus dieksekusi meskipun pengguna menutup aplikasi
Kuota
Sistem harus mengalokasikan waktu eksekusi untuk tugas yang diprioritaskan sebelum dapat berjalan. Waktu eksekusi bukannya tidak terbatas. Namun, setiap aplikasi akan menerima kuota waktu eksekusi. Setelah aplikasi menggunakan waktu eksekusinya dan mencapai kuota yang dialokasikan, Anda tidak dapat lagi mengeksekusi pekerjaan yang diprioritaskan hingga kuota diperbarui. Hal ini memungkinkan Android menyeimbangkan resource di antara aplikasi secara lebih efektif.
Jumlah waktu eksekusi yang tersedia untuk aplikasi didasarkan pada bucket standby dan tingkat kepentingan proses.
Anda dapat menentukan apa yang akan terjadi jika kuota eksekusi tidak memungkinkan pekerjaan yang diprioritaskan segera dijalankan. Lihat cuplikan di bawah untuk mengetahui detailnya.
Mengeksekusi pekerjaan yang diprioritaskan
Mulai WorkManager 2.7, aplikasi dapat memanggil setExpedited()
untuk mendeklarasikan bahwa
WorkRequest
harus berjalan secepat mungkin menggunakan tugas yang diprioritaskan. Cuplikan
kode berikut memberikan contoh cara menggunakan setExpedited()
:
Kotlin
val request = OneTimeWorkRequestBuilder<SyncWorker>() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build() WorkManager.getInstance(context) .enqueue(request)
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>() .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build();
Dalam contoh ini, kita melakukan inisialisasi instance OneTimeWorkRequest
dan memanggil
setExpedited()
. Permintaan ini kemudian menjadi pekerjaan yang diprioritaskan. Jika kuota
memungkinkan, tugas akan mulai berjalan segera di latar belakang. Jika kuota telah
digunakan, parameter OutOfQuotaPolicy
menunjukkan bahwa permintaan harus
dijalankan sebagai pekerjaan normal, bukan pekerjaan yang dipercepat.
Kompatibilitas mundur dan layanan latar depan
Untuk mempertahankan kompatibilitas mundur bagi tugas yang diprioritaskan, WorkManager mungkin menjalankan layanan latar depan pada versi platform yang lebih lama dari Android 12. Layanan latar depan dapat menampilkan notifikasi kepada pengguna.
Metode getForegroundInfoAsync()
dan getForegroundInfo()
di dalam Pekerja
memungkinkan WorkManager menampilkan notifikasi saat Anda memanggil setExpedited()
sebelum Android 12.
Setiap ListenableWorker
harus mengimplementasikan metode getForegroundInfo
jika Anda
ingin meminta agar tugas berjalan sebagai tugas yang diprioritaskan.
Saat menargetkan Android 12 atau yang lebih tinggi, layanan latar depan akan tetap tersedia untuk
Anda melalui metode setForeground
yang sesuai.
Pekerja
Pekerja tidak mengetahui pekerjaan yang mereka lakukan diprioritaskan atau tidak. Namun,
pekerja dapat menampilkan notifikasi di beberapa versi Android saat
WorkRequest
telah diprioritaskan.
Untuk mengaktifkannya, WorkManager menyediakan metode getForegroundInfoAsync()
,
yang harus Anda implementasikan agar WorkManager dapat menampilkan notifikasi untuk memulai
ForegroundService
jika diperlukan.
CoroutineWorker
Jika menggunakan CoroutineWorker
, Anda harus mengimplementasikan getForegroundInfo()
. Anda
kemudian meneruskannya ke setForeground()
dalam doWork()
. Jika Anda melakukannya,
notifikasi di versi Android akan dibuat sebelum versi 12.
Perhatikan contoh berikut:
class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
CoroutineWorker(appContext, workerParams) {
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID, createNotification()
)
}
override suspend fun doWork(): Result {
TODO()
}
private fun createNotification() : Notification {
TODO()
}
}
Kebijakan kuota
Anda dapat mengontrol apa yang terjadi pada pekerjaan yang diprioritaskan saat aplikasi mencapai
kuota eksekusinya. Untuk melanjutkan, Anda dapat meneruskan setExpedited()
:
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST
, yang menyebabkan pekerjaan dijalankan sebagai permintaan pekerjaan biasa. Cuplikan di atas menunjukkan hal tersebut.OutOfQuotaPolicy.DROP_WORK_REQUEST
, yang menyebabkan permintaan dibatalkan jika tidak ada cukup kuota.
Aplikasi contoh
Untuk melihat contoh lengkap tentang cara WorkManager 2.7.0 menggunakan pekerjaan yang diprioritaskan, lihat WorkManagerSample di GitHub.
Pekerjaan yang diprioritaskan yang ditunda
Sistem akan mencoba mengeksekusi suatu tugas yang diprioritaskan sesegera mungkin setelah tugas tersebut dipanggil. Namun, seperti halnya dengan jenis tugas lain, sistem dapat menunda permulaan pekerjaan baru yang diprioritaskan, seperti dalam kasus berikut:
- Beban: Beban sistem terlalu tinggi, yang dapat terjadi jika terlalu banyak tugas yang sudah berjalan, atau saat sistem tidak memiliki cukup memori.
- Kuota: Batas kuota tugas yang diprioritaskan telah terlampaui. Pekerjaan yang diprioritaskan menggunakan sistem kuota yang didasarkan pada Bucket Aplikasi Standby dan membatasi waktu eksekusi maksimum dalam jendela waktu yang bergulir. Kuota yang digunakan untuk tugas yang diprioritaskan lebih ketat dibandingkan dengan kuota yang digunakan untuk jenis tugas latar belakang lainnya.
Menjadwalkan pekerjaan berkala
Terkadang, aplikasi Anda mungkin memerlukan pekerjaan tertentu untuk dijalankan secara berkala. Misalnya, Anda mungkin perlu mencadangkan data, mendownload konten baru di aplikasi, atau mengupload log ke server secara berkala.
Berikut adalah cara menggunakan PeriodicWorkRequest
untuk membuat
objek WorkRequest
yang dieksekusi secara berkala:
Kotlin
val saveRequest = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS) // Additional configuration .build()
Java
PeriodicWorkRequest saveRequest = new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS) // Constraints .build();
Dalam contoh ini, pekerjaan dijadwalkan dengan interval satu jam.
Periode interval didefinisikan sebagai waktu minimum di antara pengulangan. Waktu pasti eksekusi pekerja bergantung pada batasan yang Anda gunakan dalam objek WorkRequest dan pada pengoptimalan yang dilakukan oleh sistem.
Interval proses fleksibel
Jika sifat pekerjaan Anda sangat bergantung pada waktu eksekusi, Anda dapat mengonfigurasikan
PeriodicWorkRequest
untuk berjalan pada periode
fleksibel dalam setiap periode interval, seperti yang ditunjukkan pada Gambar 1.
Gambar 1. Diagram menunjukkan interval pengulangan dengan periode fleksibel yang dapat digunakan untuk menjalankan pekerjaan.
Untuk menentukan pekerjaan berkala dengan periode flex, Anda perlu meneruskan flexInterval
dengan repeatInterval
saat membuat PeriodicWorkRequest
. Periode flex
dimulai pada repeatInterval - flexInterval
, dan berlanjut ke akhir interval.
Berikut adalah contoh pekerjaan berkala yang dapat dijalankan selama 15 menit terakhir dari setiap periode satu jam.
Kotlin
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>( 1, TimeUnit.HOURS, // repeatInterval (the period cycle) 15, TimeUnit.MINUTES) // flexInterval .build()
Java
WorkRequest saveRequest = new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS, 15, TimeUnit.MINUTES) .build();
Interval berulang harus lebih besar dari atau sama dengan
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS
dan interval fleksibel
harus lebih besar dari atau sama dengan
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS
.
Pengaruh Batasan pada Pekerjaan Berkala
Anda dapat menerapkan batasan untuk tugas berkala. Misalnya, Anda dapat menambahkan
batasan ke permintaan tugas sehingga tugas hanya akan berjalan saat perangkat pengguna
mengisi daya. Dalam kasus ini, meskipun interval pengulangan yang ditentukan berlalu,
PeriodicWorkRequest
tidak akan berjalan sampai kondisi ini terpenuhi. Hal ini dapat
menyebabkan proses tertentu dari pekerjaan Anda menjadi tertunda, atau bahkan dilewati jika
kondisi tidak terpenuhi dalam interval eksekusi.
Batasan pekerjaan
Batasan memastikan bahwa pekerjaan ditunda hingga kondisi optimal terpenuhi. Batasan berikut tersedia untuk WorkManager.
NetworkType | Batasi jenis jaringan yang diperlukan agar pekerjaan Anda dapat berjalan.
Misalnya, Wi-Fi (UNMETERED ).
|
BatteryNotLow | Bila disetel ke benar (true), pekerjaan Anda tidak akan berjalan jika perangkat dalam mode baterai lemah. |
RequiresCharging | Jika disetel ke benar (true), pekerjaan Anda hanya akan berjalan saat perangkat sedang diisi dayanya. |
DeviceIdle | Jika disetel ke benar (true), tindakan ini mengharuskan perangkat pengguna tidak beraktivitas sebelum pekerjaan berjalan. Tindakan ini berguna untuk menjalankan operasi batch yang mungkin berdampak negatif pada performa aplikasi lain yang berjalan secara aktif pada perangkat pengguna. |
StorageNotLow | Jika disetel ke benar (true), pekerjaan Anda tidak akan berjalan jika ruang penyimpanan pengguna di perangkat terlalu rendah. |
Untuk membuat kumpulan batasan dan mengaitkannya ke beberapa tugas, buat instance
Constraints
menggunakan Contraints.Builder()
dan tetapkan ke
WorkRequest.Builder()
.
Misalnya, kode berikut membuat permintaan kerja yang hanya berjalan saat perangkat pengguna mengisi daya dan menggunakan Wi-Fi:
Kotlin
val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresCharging(true) .build() val myWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setConstraints(constraints) .build()
Java
Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .setRequiresCharging(true) .build(); WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setConstraints(constraints) .build();
Saat beberapa batasan ditentukan, pekerjaan hanya akan berjalan jika semua batasan terpenuhi.
Jika batasan menjadi tidak stabil saat pekerjaan berjalan, WorkManager akan menghentikan pekerja. Pekerjaan tersebut kemudian akan dicoba lagi setelah semua batasan terpenuhi.
Pekerjaan Tertunda
Jika pekerjaan Anda tidak memiliki batasan atau semua batasan terpenuhi saat pekerjaan diantrekan, sistem dapat memilih untuk langsung menjalankan pekerjaan ini. Jika tidak ingin tugas dijalankan langsung, Anda dapat menentukan tugas agar dimulai setelah penundaan awal minimum.
Berikut adalah contoh cara menetapkan pekerjaan agar berjalan minimal 10 menit setelah diantrekan.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setInitialDelay(10, TimeUnit.MINUTES) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setInitialDelay(10, TimeUnit.MINUTES) .build();
Meskipun contoh menggambarkan cara menetapkan penundaan awal untuk
OneTimeWorkRequest
, Anda juga dapat menetapkan penundaan awal untuk
PeriodicWorkRequest
. Dalam hal ini, hanya operasi pertama dari pekerjaan berkala Anda
yang akan ditunda.
Kebijakan percobaan ulang dan backoff
Jika Anda mengharuskan WorkManager untuk mencoba kembali tugas, Anda dapat mengembalikan
Result.retry()
dari pekerja. Pekerjaan Anda akan
dijadwalkan ulang sesuai dengan penundaan backoff dan kebijakan backoff.
Penundaan backoff menentukan jumlah waktu minimum untuk menunggu sebelum mencoba kembali pekerjaan Anda setelah upaya pertama. Nilai ini tidak boleh kurang dari 10 detik (atau MIN_BACKOFF_MILLIS).
Kebijakan backoff menentukan bagaimana keterlambatan backoff akan meningkat dari waktu ke waktu untuk upaya percobaan ulang berikutnya. WorkManager mendukung 2 kebijakan backoff,
LINEAR
danEXPONENTIAL
.
Setiap permintaan pekerjaan memiliki kebijakan backoff dan penundaan backoff. Kebijakan defaultnya
adalah EXPONENTIAL
dengan penundaan selama 30 detik, tetapi Anda dapat menggantinya di
konfigurasi permintaan kerja.
Berikut adalah contoh penyesuaian kebijakan dan penundaan backoff.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build();
Dalam contoh ini, penundaan backoff minimum ditetapkan ke nilai minimum yang diizinkan,
10 detik. Karena kebijakannya adalah LINEAR
, interval percobaan ulang akan meningkat
sekitar 10 detik dengan setiap upaya baru. Misalnya, penyelesaian pertama
dengan Result.retry()
akan dicoba lagi setelah 10 detik,
diikuti dengan 20, 30, 40, dan seterusnya, jika pekerjaan terus mengembalikan
Result.retry()
setelah upaya berikutnya. Jika kebijakan backoff ditetapkan ke
EXPONENTIAL
, urutan durasi percobaan ulang akan menjadi lebih dekat ke 20, 40, 80, dan
seterusnya.
Memberi tag pekerjaan
Setiap permintaan pekerjaan memiliki pengenal unik, yang dapat digunakan untuk mengidentifikasi pekerjaan tersebut nanti untuk membatalkan pekerjaan atau mengamati progresnya.
Jika memiliki grup tugas yang terkait secara logis, Anda juga dapat membantu untuk memberi tag item tugas tersebut. Pemberian tag memungkinkan Anda untuk beroperasi dengan sekelompok permintaan tugas bersama-sama.
Misalnya, WorkManager.cancelAllWorkByTag(String)
membatalkan
semua permintaan pekerjaan dengan tag tertentu, dan
WorkManager.getWorkInfosByTag(String)
menampilkan daftar objek
WorkInfo yang dapat digunakan untuk menentukan status pekerjaan saat ini.
Kode berikut menunjukkan cara menambahkan tag "pembersihan" ke pekerjaan:
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .addTag("cleanup") .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .addTag("cleanup") .build();
Terakhir, beberapa tag dapat ditambahkan ke satu permintaan pekerjaan. Secara internal,
tag ini disimpan sebagai kumpulan string. Untuk mendapatkan kumpulan tag yang dikaitkan dengan
WorkRequest
, Anda dapat menggunakan WorkInfo.getTags().
Dari class Worker
, Anda dapat mengambil kumpulan tag-nya melalui
ListenableWorker.getTags().
Menetapkan data input
Tugas Anda mungkin memerlukan data input agar dapat melakukan pekerjaannya. Misalnya, tugas yang menangani upload gambar mungkin memerlukan URI gambar untuk diupload sebagai input.
Nilai input disimpan sebagai key-value pair dalam objek
Data
dan dapat ditetapkan pada permintaan pekerjaan. WorkManager akan mengirimkan input Data
ke
tugas Anda saat menjalankan tugas. Class Worker
dapat mengakses
argumen input dengan memanggil Worker.getInputData()
. Kode
di bawah ini menunjukkan cara membuat instance Worker
yang
memerlukan data input dan cara mengirimkannya dalam permintaan tugas Anda.
Kotlin
// Define the Worker requiring input class UploadWork(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) { override fun doWork(): Result { val imageUriInput = inputData.getString("IMAGE_URI") ?: return Result.failure() uploadFile(imageUriInput) return Result.success() } ... } // Create a WorkRequest for your Worker and sending it input val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>() .setInputData(workDataOf( "IMAGE_URI" to "http://..." )) .build()
Java
// Define the Worker requiring input public class UploadWork extends Worker { public UploadWork(Context appContext, WorkerParameters workerParams) { super(appContext, workerParams); } @NonNull @Override public Result doWork() { String imageUriInput = getInputData().getString("IMAGE_URI"); if(imageUriInput == null) { return Result.failure(); } uploadFile(imageUriInput); return Result.success(); } ... } // Create a WorkRequest for your Worker and sending it input WorkRequest myUploadWork = new OneTimeWorkRequest.Builder(UploadWork.class) .setInputData( new Data.Builder() .putString("IMAGE_URI", "http://...") .build() ) .build();
Demikian pula, class Data
dapat digunakan untuk menampilkan nilai hasil. Data input dan
output dibahas secara lebih mendetail di bagian parameter input dan
nilai yang ditampilkan.
Langkah Berikutnya
Di halaman Status dan pengamatan, Anda akan mempelajari lebih lanjut status pekerjaan dan cara memantau progres pekerjaan.