Threading در Worker

وقتی از Worker استفاده می کنید، WorkManager به طور خودکار Worker.doWork() در یک رشته پس زمینه فراخوانی می کند. رشته پس زمینه از Executor مشخص شده در WorkManager's Configuration می آید. به‌طور پیش‌فرض، WorkManager یک Executor را برای شما تنظیم می‌کند — اما می‌توانید برنامه خود را نیز سفارشی کنید. برای مثال، می‌توانید یک اجراکننده پس‌زمینه موجود را در برنامه خود به اشتراک بگذارید، یک Executor تک رشته‌ای ایجاد کنید تا مطمئن شوید که تمام کارهای پس‌زمینه شما به صورت متوالی اجرا می‌شوند، یا حتی یک Executor سفارشی را مشخص کنید. برای سفارشی کردن Executor ، مطمئن شوید که WorkManager را به صورت دستی مقداردهی اولیه کنید.

هنگام پیکربندی WorkManager به صورت دستی، می توانید Executor خود را به صورت زیر مشخص کنید:

کاتلین

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

جاوا

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

در اینجا یک مثال از یک Worker ساده است که محتویات یک صفحه وب را 100 بار دانلود می کند:

کاتلین

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()
    }
}

جاوا

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() یک فراخوانی همزمان است—از شما انتظار می‌رود که کل کار پس‌زمینه خود را به صورت مسدود انجام دهید و تا زمان خروج از متد آن را به پایان برسانید. اگر یک API ناهمزمان را در doWork() فراخوانی کنید و یک Result برگردانید، ممکن است پاسخ تماس شما به درستی کار نکند. اگر در این موقعیت قرار گرفتید، از ListenableWorker استفاده کنید (به Threading در ListenableWorker مراجعه کنید).

هنگامی که یک Worker در حال اجرا به هر دلیلی متوقف شود، یک تماس با Worker.onStopped() دریافت می کند. این روش را لغو کنید یا با Worker.isStopped() تماس بگیرید تا کد خود را بررسی کنید و در صورت لزوم منابع را آزاد کنید. هنگامی که Worker در مثال بالا متوقف می شود، ممکن است در وسط حلقه بارگیری آیتم ها باشد و حتی اگر متوقف شده باشد به این کار ادامه می دهد. برای بهینه سازی این رفتار، می توانید کاری شبیه به این انجام دهید:

کاتلین

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()
    }
}

جاوا

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 متوقف شد، مهم نیست که چه چیزی را از Worker.doWork() برگردانید. Result نادیده گرفته خواهد شد.