WorkManager adalah API untuk penjadwalan background task pada Android yang bersifat asynchronous. WorkManager manager sendiri adalah proses yang bersifat asynchronous dalam background thread jadi tidak bersifat blocking. Namun implementasi method doWork dari class Worker dalam WorkManager bersifat synchronous yang berarti bahwa proses akan dianggap selesai jika sudah ada return dari method tersebut.
Jika menggunakan library yang berbasis callback-based asynchronous seperti Asynchronous Http Client (loopj) tentunya akan bermasalah karena method doWork akan langsung dianggap selesai. Hal ini disebabkan karena library http clientnya bekerja pada thread yang terpisah dari thread WorkManager dan method doWork langsung mengembalikan return value.
Untuk lebih jelasnya mari lihat kode di bawah ini:
public class SyncWorker extends Worker {
public SyncWorker(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
}
@Override
public Result doWork() {
syncData();
return Result.success();
}
}
Perhatikan method doWork, jika proses syncData bersifat synchronous maka baris return Result.success akan dipanggil jika proses dalam syncData selesai. Nah, jika proses syncData sendiri bersifat asyncronous seperti pada baris kode di bawah, maka baris return Result.success() akan langsung dipanggil sementara proses dalam syncData masih berlangsung. Hal ini akan menimbulkan behaviour yang tidak diinginkan karena object SyncWorker sendiri kemungkinan akan distop dan proses dalam syncData akan terputus.
private void syncData() {
AsyncHttpClient client = new AsyncHttpClient();
client.get("https://api.example.com/sync.json", new AsyncHttpResponseHandler() {
@Override
public void onStart() {
}
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
}
@Override
public void onRetry(int retryNo) {
}
});
}
Solusi untuk permasalahan di atas adalah mengganti class Worker dengan ListenableWorker. ListenableWorker adalah class dalam WorkManager yang didesign untuk melakukan proses-proses yang bersifat asynchronous. Mari kita update kode di atas dengan mengimplementasikan class ListanableWorker.
import androidx.work.ListenableWorker;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.annotation.NonNull;
import com.google.common.util.concurrent.ListenableFuture;
public class SyncWorker extends ListenableWorker {
public SyncWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
AsyncHttpClient client = new AsyncHttpClient();
client.get("https://api.example.com/sync.json", new AsyncHttpResponseHandler() {
@Override
public void onStart() {
}
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
completer.set(Result.success());
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
completer.set(Result.failure());
}
@Override
public void onRetry(int retryNo) {
}
});
}
}
Perhatikan baris kode diatas, proses asynchronous dari AsyncHttpClient akan tetap berjalan sampai callback AsyncHttpResponseHandler dipanggil. Background proses dari SyncWorker akan dianggap selesai saat completer.set(Result.failure)) dari method onFailure atau completer.set(Result.success()) dari method onSuccess dipanggil. Mudah bukan?
API WorkManager sendiri merupakan bagian dari library AndroidX sehingga kita perlu mengaktifkannya dari Android Studio. Berikut beberapa file yang harus diupdate untuk mengaktifkan AndroidX dan WorkManager
Tambahkan baris di bawah ini pada file gradle.properties
android.enableJetifier=true
android.useAndroidX=true
Pada file build.gradle module/app
....
android {
compileSdkVersion 28
buildToolsVersion "30.0.0"
.....
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
....
implementation 'androidx.work:work-runtime:2.4.0-rc01'
implementation 'androidx.concurrent:concurrent-futures:1.0.0'
.....
}
}
....
Happy coding…;)
Leave a Reply