Firebase JobDispatcher থেকে WorkManager-এ স্থানান্তরিত হচ্ছে

WorkManager হল Android-এ স্থগিত ব্যাকগ্রাউন্ডের কাজের সময়সূচী ও নির্বাহের জন্য একটি লাইব্রেরি। এটি Firebase JobDispatcher-এর জন্য প্রস্তাবিত প্রতিস্থাপন। নিম্নলিখিত নির্দেশিকা আপনাকে আপনার Firebase JobDispatcher বাস্তবায়নকে WorkManager-এ স্থানান্তরিত করার প্রক্রিয়ার মধ্য দিয়ে নিয়ে যাবে।

গ্রেডল সেটআপ

আপনার Android প্রকল্পে WorkManager লাইব্রেরি আমদানি করতে, Getting start with WorkManager- এ তালিকাভুক্ত নির্ভরতা যোগ করুন।

জব সার্ভিস থেকে কর্মী পর্যন্ত

FirebaseJobDispatcher JobService একটি সাবক্লাস ব্যবহার করে একটি এন্ট্রি পয়েন্ট হিসাবে কাজটি সংজ্ঞায়িত করার জন্য যা করা দরকার। আপনি হয়তো সরাসরি JobService ব্যবহার করছেন, অথবা SimpleJobService ব্যবহার করছেন।

একটি JobService দেখতে এরকম কিছু হবে:

কোটলিন

import com.firebase.jobdispatcher.JobParameters
import com.firebase.jobdispatcher.JobService

class MyJobService : JobService() {
    override fun onStartJob(job: JobParameters): Boolean {
        // Do some work here
        return false // Answers the question: "Is there still work going on?"
    }
    override fun onStopJob(job: JobParameters): Boolean {
        return false // Answers the question: "Should this job be retried?"
    }
}

জাভা

import com.firebase.jobdispatcher.JobParameters;
import com.firebase.jobdispatcher.JobService;

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters job) {
        // Do some work here

        return false; // Answers the question: "Is there still work going on?"
    }

    @Override
    public boolean onStopJob(JobParameters job) {
        return false; // Answers the question: "Should this job be retried?"
    }
}

আপনি যদি SimpleJobService ব্যবহার করেন তাহলে আপনি onRunJob() ওভাররাইড করবেন, যা @JobResult int টাইপ প্রদান করে।

মূল পার্থক্য হল আপনি যখন সরাসরি JobService ব্যবহার করছেন, onStartJob() কে মূল থ্রেডে কল করা হয় এবং কাজটিকে একটি ব্যাকগ্রাউন্ড থ্রেডে অফলোড করার দায়িত্ব অ্যাপের। অন্যদিকে, আপনি যদি SimpleJobService ব্যবহার করেন, তাহলে সেই পরিষেবাটি একটি ব্যাকগ্রাউন্ড থ্রেডে আপনার কাজ সম্পাদনের জন্য দায়ী।

WorkManager এর অনুরূপ ধারণা আছে। WorkManager-এ কাজের মৌলিক একক হল একজন ListenableWorker । এছাড়াও শ্রমিকদের অন্যান্য দরকারী উপপ্রকার যেমন Worker , RxWorker , এবং CoroutineWorker (যখন Kotlin coroutines ব্যবহার করে)।

JobService মানচিত্র একটি ListenableWorker

আপনি যদি সরাসরি JobService ব্যবহার করেন, তাহলে এটি যে কর্মীকে ম্যাপ করে সেটি হল ListenableWorker । আপনি যদি SimpleJobService ব্যবহার করেন তবে আপনার পরিবর্তে Worker ব্যবহার করা উচিত।

আসুন উপরের উদাহরণটি ব্যবহার করি ( MyJobService ) এবং দেখুন কিভাবে আমরা এটিকে ListenableWorker এ রূপান্তর করতে পারি।

কোটলিন

import android.content.Context
import androidx.work.ListenableWorker
import androidx.work.ListenableWorker.Result
import androidx.work.WorkerParameters
import com.google.common.util.concurrent.ListenableFuture

class MyWorker(appContext: Context, params: WorkerParameters) :
    ListenableWorker(appContext, params) {

    override fun startWork(): ListenableFuture<ListenableWorker.Result> {
        // Do your work here.
        TODO("Return a ListenableFuture<Result>")
    }

    override fun onStopped() {
        // Cleanup because you are being stopped.
    }
}

জাভা

import android.content.Context;
import androidx.work.ListenableWorker;
import androidx.work.ListenableWorker.Result;
import androidx.work.WorkerParameters;
import com.google.common.util.concurrent.ListenableFuture;

class MyWorker extends ListenableWorker {

  public MyWorker(@NonNull Context appContext, @NonNull WorkerParameters params) {
    super(appContext, params);
  }

  @Override
  public ListenableFuture<ListenableWorker.Result> startWork() {
    // Do your work here.
    Data input = getInputData();

    // Return a ListenableFuture<>
  }

  @Override
  public void onStopped() {
    // Cleanup because you are being stopped.
  }
}

WorkManager-এ কাজের মৌলিক একক হল ListenableWorkerJobService.onStartJob() এর মত, startWork() মূল থ্রেডে কল করা হয়। এখানে MyWorker ListenableWorker প্রয়োগ করে এবং ListenableFuture এর একটি উদাহরণ প্রদান করে, যা অসিঙ্ক্রোনাসভাবে কাজ সমাপ্তির সংকেত দিতে ব্যবহৃত হয়। এখানে আপনার নিজের থ্রেডিং কৌশল বেছে নেওয়া উচিত।

এখানে ListenableFuture অবশেষে একটি ListenableWorker.Result ধরন প্রদান করে যা Result.success() , Result.success(Data outputData) , Result.retry() , Result.failure() , অথবা Result.failure(Data outputData) এর মধ্যে একটি হতে পারে। আরও তথ্যের জন্য, ListenableWorker.Result এর রেফারেন্স পৃষ্ঠাটি দেখুন।

onStopped() কে বলা হয় যে সংকেত দিতে হবে যে ListenableWorker থামতে হবে, হয় কারণ সীমাবদ্ধতাগুলি আর পূরণ হচ্ছে না (উদাহরণস্বরূপ, কারণ নেটওয়ার্ক আর উপলব্ধ নেই), অথবা একটি WorkManager.cancel…() পদ্ধতি কল করা হয়েছিল। OS যদি কোনো কারণে আপনার কাজ বন্ধ করার সিদ্ধান্ত নেয় তাহলে onStopped() কল করা যেতে পারে।

একজন কর্মীকে SimpleJobService মানচিত্র

SimpleJobService ব্যবহার করার সময় উপরের কর্মী দেখতে পাবেন:

কোটলিন

import android.content.Context;
import androidx.work.Data;
import androidx.work.ListenableWorker.Result;
import androidx.work.Worker;
import androidx.work.WorkerParameters;


class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        TODO("Return a Result")
    }

    override fun onStopped() {
        super.onStopped()
        TODO("Cleanup, because you are being stopped")
    }
}

জাভা

import android.content.Context;
import androidx.work.Data;
import androidx.work.ListenableWorker.Result;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

class MyWorker extends Worker {

  public MyWorker(@NonNull Context appContext, @NonNull WorkerParameters params) {
    super(appContext, params);
  }

  @Override
  public Result doWork() {
    // Do your work here.
    Data input = getInputData();

    // Return a ListenableWorker.Result
    Data outputData = new Data.Builder()
        .putString(Key, value)
        .build();
    return Result.success(outputData);
  }

  @Override
  public void onStopped() {
    // Cleanup because you are being stopped.
  }
}

এখানে doWork() ListenableWorker.Result এর একটি উদাহরণ প্রদান করে। সিঙ্ক্রোনাসভাবে কাজ সমাপ্তির সংকেত দেয়। এটি SimpleJobService এর অনুরূপ, যা একটি ব্যাকগ্রাউন্ড থ্রেডে কাজের সময় নির্ধারণ করে।

Jobbuilder ম্যাপ ওয়ার্করিকোয়েস্টে

FirebaseJobBuilder Job.Builder ব্যবহার করে Job মেটাডেটা উপস্থাপন করে। WorkManager এই ভূমিকাটি পূরণ করতে WorkRequest ব্যবহার করে।

WorkManager-এর দুই ধরনের WorkRequest আছে: OneTimeWorkRequest এবং PeriodicWorkRequest

আপনি যদি বর্তমানে Job.Builder.setRecurring(true) ব্যবহার করছেন, তাহলে আপনার একটি নতুন PeriodicWorkRequest তৈরি করা উচিত। অন্যথায়, আপনার একটি OneTimeWorkRequest ব্যবহার করা উচিত।

FirebaseJobDispatcher এর সাথে একটি জটিল Job সময়সূচী কেমন হতে পারে তা দেখা যাক:

কোটলিন

val input: Bundle = Bundle().apply {
    putString("some_key", "some_value")
}

val job = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyService::class.java)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job
    .setRecurring(false)
    // don't persist past a device reboot
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)

    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(input)
    .build()

dispatcher.mustSchedule(job)

জাভা

Bundle input = new Bundle();
input.putString("some_key", "some_value");

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // one-off job
    .setRecurring(false)
    // don't persist past a device reboot
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT)
    // start between 0 and 60 seconds from now
    .setTrigger(Trigger.executionWindow(0, 60))
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // retry with exponential backoff
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
    // constraints that need to be satisfied for the job to run
    .setConstraints(
        // only run on an unmetered network
        Constraint.ON_UNMETERED_NETWORK,
        // only run when the device is charging
        Constraint.DEVICE_CHARGING
    )
    .setExtras(input)
    .build();

dispatcher.mustSchedule(myJob);

WorkManager-এর সাথে এটি অর্জন করতে আপনার প্রয়োজন হবে:

  • ইনপুট ডেটা তৈরি করুন যা Worker জন্য ইনপুট হিসাবে ব্যবহার করা যেতে পারে।
  • FirebaseJobDispatcher এর জন্য উপরে বর্ণিত ইনপুট ডেটা এবং সীমাবদ্ধতাগুলির সাথে একটি WorkRequest তৈরি করুন।
  • WorkRequest সারিবদ্ধ করুন।

কর্মীর জন্য ইনপুট সেট আপ করা

FirebaseJobDispatcher JobService এ ইনপুট ডেটা পাঠাতে একটি Bundle ব্যবহার করে। WorkManager পরিবর্তে Data ব্যবহার করে। তাই এটি হয়ে যায়:

কোটলিন

import androidx.work.workDataOf
val data = workDataOf("some_key" to "some_val")

জাভা

import androidx.work.Data;
Data input = new Data.Builder()
    .putString("some_key", "some_value")
    .build();

কর্মীর জন্য সীমাবদ্ধতা স্থাপন করা

FirebaseJobDispatcher চাকরিতে সীমাবদ্ধতা সেট আপ করতে Job.Builder.setConstaints(...) ব্যবহার করে। WorkManager পরিবর্তে Constraints ব্যবহার করে।

কোটলিন

import androidx.work.*

val constraints: Constraints = Constraints.Builder().apply {
    setRequiredNetworkType(NetworkType.CONNECTED)
    setRequiresCharging(true)
}.build()

জাভা

import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;

Constraints constraints = new Constraints.Builder()
    // The Worker needs Network connectivity
    .setRequiredNetworkType(NetworkType.CONNECTED)
    // Needs the device to be charging
    .setRequiresCharging(true)
    .build();

কাজের অনুরোধ তৈরি করা (এক সময় বা পর্যায়ক্রমিক)

OneTimeWorkRequest s এবং PeriodicWorkRequest তৈরি করতে আপনাকে OneTimeWorkRequest.Builder এবং PeriodicWorkRequest.Builder ব্যবহার করতে হবে।

উপরের Job অনুরূপ একটি OneTimeWorkRequest তৈরি করতে আপনাকে নিম্নলিখিতগুলি করতে হবে:

কোটলিন

import androidx.work.*
import java.util.concurrent.TimeUnit

val constraints: Constraints = TODO("Define constraints as above")
val request: OneTimeWorkRequest =
     // Tell which work to execute
     OneTimeWorkRequestBuilder<MyWorker>()
         // Sets the input data for the ListenableWorker
        .setInputData(input)
        // If you want to delay the start of work by 60 seconds
        .setInitialDelay(60, TimeUnit.SECONDS)
        // Set a backoff criteria to be used when retry-ing
        .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30000, TimeUnit.MILLISECONDS)
        // Set additional constraints
        .setConstraints(constraints)
        .build()

জাভা

import androidx.work.BackoffCriteria;
import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OneTimeWorkRequest.Builder;
import androidx.work.Data;

// Define constraints (as above)
Constraints constraints = ...
OneTimeWorkRequest request =
    // Tell which work to execute
    new OneTimeWorkRequest.Builder(MyWorker.class)
        // Sets the input data for the ListenableWorker
        .setInputData(inputData)
        // If you want to delay the start of work by 60 seconds
        .setInitialDelay(60, TimeUnit.SECONDS)
        // Set a backoff criteria to be used when retry-ing
        .setBackoffCriteria(BackoffCriteria.EXPONENTIAL, 30000, TimeUnit.MILLISECONDS)
        // Set additional constraints
        .setConstraints(constraints)
        .build();

এখানে মূল পার্থক্য হল যে WorkManager-এর কাজগুলি সর্বদা স্বয়ংক্রিয়ভাবে ডিভাইস রিবুট জুড়ে বজায় থাকে।

আপনি যদি একটি PeriodicWorkRequest তৈরি করতে চান তাহলে আপনি এরকম কিছু করবেন:

কোটলিন

val constraints: Constraints = TODO("Define constraints as above")
val request: PeriodicWorkRequest =
PeriodicWorkRequestBuilder<MyWorker>(15, TimeUnit.MINUTES)
    // Sets the input data for the ListenableWorker
    .setInputData(input)
    // Other setters
    .build()

জাভা

import androidx.work.BackoffCriteria;
import androidx.work.Constraints;
import androidx.work.Constraints.Builder;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.PeriodicWorkRequest.Builder;
import androidx.work.Data;

// Define constraints (as above)
Constraints constraints = ...

PeriodicWorkRequest request =
    // Executes MyWorker every 15 minutes
    new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
        // Sets the input data for the ListenableWorker
        .setInputData(input)
        . // other setters (as above)
        .build();

সময়সূচী কাজ

এখন যেহেতু আপনি একজন Worker এবং একটি WorkRequest সংজ্ঞায়িত করেছেন, আপনি কাজের সময়সূচী করতে প্রস্তুত।

FirebaseJobDispatcher এর সাথে সংজ্ঞায়িত প্রতিটি Job একটি tag ছিল যা একটি Job স্বতন্ত্রভাবে সনাক্ত করতে ব্যবহৃত হত। এটি আবেদনের জন্য একটি উপায়ও প্রদান করে যাতে সময়সূচীকারীকে জানানো হয় যে যদি Job এই উদাহরণটি setReplaceCurrent কল করে Job একটি বিদ্যমান অনুলিপি প্রতিস্থাপন করা হয়।

কোটলিন

val job = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyService::class.java)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // don't overwrite an existing job with the same tag
    .setRecurring(false)
    // Other setters...
    .build()

জাভা

Job myJob = dispatcher.newJobBuilder()
    // the JobService that will be called
    .setService(MyJobService.class)
    // uniquely identifies the job
    .setTag("my-unique-tag")
    // don't overwrite an existing job with the same tag
    .setReplaceCurrent(false)
    // other setters
    // ...

dispatcher.mustSchedule(myJob);

WorkManager ব্যবহার করার সময়, আপনি enqueueUniqueWork() এবং enqueueUniquePeriodicWork() API ব্যবহার করে একই ফলাফল অর্জন করতে পারেন (যথাক্রমে একটি OneTimeWorkRequest এবং একটি PeriodicWorkRequest ব্যবহার করে)। আরও তথ্যের জন্য, WorkManager.enqueueUniqueWork() এবং WorkManager.enqueueUniquePeriodicWork() এর রেফারেন্স পৃষ্ঠাগুলি দেখুন।

এটি এমন কিছু দেখাবে:

কোটলিন

import androidx.work.*

val request: OneTimeWorkRequest = TODO("A WorkRequest")
WorkManager.getInstance(myContext)
    .enqueueUniqueWork("my-unique-name", ExistingWorkPolicy.KEEP, request)

জাভা

import androidx.work.ExistingWorkPolicy;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;

OneTimeWorkRequest workRequest = // a WorkRequest;
WorkManager.getInstance(myContext)
    // Use ExistingWorkPolicy.REPLACE to cancel and delete any existing pending
    // (uncompleted) work with the same unique name. Then, insert the newly-specified
    // work.
    .enqueueUniqueWork("my-unique-name", ExistingWorkPolicy.KEEP, workRequest);

কাজ বাতিল

FirebaseJobDispatcher এর সাথে আপনি ব্যবহার করে কাজ বাতিল করতে পারেন:

কোটলিন

dispatcher.cancel("my-unique-tag")

জাভা

dispatcher.cancel("my-unique-tag");

WorkManager ব্যবহার করার সময় আপনি ব্যবহার করতে পারেন:

কোটলিন

import androidx.work.WorkManager
WorkManager.getInstance(myContext).cancelUniqueWork("my-unique-name")

জাভা

import androidx.work.WorkManager;
WorkManager.getInstance(myContext).cancelUniqueWork("my-unique-name");

ওয়ার্ক ম্যানেজার শুরু করা হচ্ছে

WorkManager সাধারণত একটি ContentProvider ব্যবহার করে নিজেকে আরম্ভ করে। WorkManager কিভাবে সংগঠিত করে এবং সময়সূচী কাজ করে তার উপর আপনার যদি আরও নিয়ন্ত্রণের প্রয়োজন হয়, তাহলে আপনি WorkManager কনফিগারেশন এবং ইনিশিয়ালাইজেশন কাস্টমাইজ করতে পারেন।