BackgroundTaskManager API provides the ability to chain multiple tasks into a singleton instance of backgroundTaskManager.It also includes the ability to process tasks SERIALLY ( tasks processed one after another) or in PARALLEL ( multiple tasks processed simultaneously). This library handles thread processing as required and is optimised to handle tasks efficiently. Maximum PARALLEL tasks that can be executed simultaneously is computed and processed accordingly. If the TaskQueue exceeds the maximum available cores of a CPU, the all subsequent tasks are queued for execution. This also includes extended features invoking a callable function before or after completion of the tasks. This feature is wrapped in a familiar and easy method called before() and then().
Before you begin, ensure you have met the following requirements:
- You have installed the latest version of Android Studio and gradle.
- uuhhmmmm... nothing else.....
βΊοΈ
Tasks are processed simultaneously reducing the runtime.
Tasks are processed one after other.
Add this gradle dependecy to your app level build.gradle file
implementation 'com.github.JerrySJoseph:BackgroundTaskManager:v1.0.1-alpha'
Don't forget to add jitpack in your project level build.gradle file
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING) //for running tasks simultaneously
OR
BackgroundTaskManager.getInstance(BackgroundTaskType.SERIAL_PROCESSING) // for runnning tasks one after other
BackgroundTaskManager provides add() method to add multiple tasks to the TaskQueue for execution. Here is an example of chaining these Tasks,
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.add(bgTask)
.execute();
add() method accepts runnable or an abstract implementation of BackgroundTask class provided in this library.
Runnable bgTask= new Runnable() {
@Override
public void run() {
//Some LONG Running background task
}
};
NOTE: Use Runnable when you do not require any result from the task. for eg: a backup operation, sending an status ping, etc.. If you want a result returned from the task, you will have to implement BackgroundTask class (just like AsyncTask<Param,Progress,Result>)
You can add multiple tasks to the TaskQueue for execution. If the instance is created for SERIAL processing, all tasks will be executed one after other. On the other hand if the instance is of PARALLEL Processing, the library will calculate maxing possible simultaneous tasks that can be run maximizing the efficiency. All subsequent tasks will be queued and processed when other threads become idle. Here is an example of how to chain multiple tasks,
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.add(bgTask1)
.add(bgTask2)
.add(bgTask3)
.add(bgTask4)
.add(bgTask5)
....
.execute();
invoke execute() method to start the queue processing.
This library provides an abstract class BackgroundTask to implement your own custom task class. Below is an example demonstrating a custom class tailored to facilitate Download of a file from Network.
/**
BackgroundTask<Result,Progress,Params> follows AsyncTask pattern to create custom task.
Result -> Type of Result you are expecting from the Task ( String in this case)
Progress -> Type of progress update ( Integer in this case to denote % of download completed )
Params -> Type of the Parameters that we need to pass (String in this case for URL of file to be downloaded)
*/
public class DownloadTask extends BackgroundTask<String,Integer,String>{
String taskName;
public DownloadTask(String taskName, String... strings) {
super(strings);
this.taskName = taskName;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
//Invoked before starting execution of Queue
//This is the block where you would want to show any type of dialog for progress update
}
@Override
protected void onResult(String s) {
//Invoked when a result from this task is recieved.
}
@Override
protected void onCancelled() {
super.onCancelled();
//Invoked when this task gets cancelled anyhow.
}
@Override
protected String doWork(String... strings) throws Exception {
//Faking a long download progress
//You can implement your own logic to fetch Data from Network
for(int i=0;i<5;i++)
{
Thread.sleep(1000);
//method to publish progress update
publishProgress((i+1)*20);
}
return "complete";
}
@Override
protected void onProgressUpdated(Integer integer) {
super.onProgressUpdated(integer);
//This is invoked when an update in progress is recieved.
}
@Override
protected void onException(Exception exception) {
//Invoked when an exception is occured while doing the task
}
@Override
protected void onStatusChanged(Status s) {
super.onStatusChanged(s);
//Invoked when status of the task changes
//Status available are : PENDING,RUNNING,FINISHED,CANCELLED,ERROR
}
}
After creating this custom class, we can chain objects of this task like
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.add(new DownloadTask("Download_Task_1","param1","param2","param3"))
.add(new DownloadTask("Download_Task_2","param1","param2","param3"))
.add(new DownloadTask("Download_Task_3","param1","param2","param3"))
.add(new DownloadTask("Download_Task_4","param1","param2","param3"))
.execute()
Tasks which are referenced by ID can be cancelled individually. To cancel a task by its ID,
BackgroundTaskManager.cancelTask(taskID); //Cancel the task with taskID if its not running.
....
BackgroundTaskManager.cancelTask(taskID,true); //Cancel the task with taskID even if its running.
Inorder for cancelling to work, you need to have the taskID for every process. Task ID can be fetched from BackgroundTaskManager by a static method getIDbyTask();
String taskID = BackgroundTaskManager.getIDbyTask(taskObject);
Alternatively, we can pass custom taskID while adding tasks to Queues,
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.add("Download_Task_1",new DownloadTask("Download_Task_1","param1","param2","param3")) //passing taskID
.add("Download_Task_2",new DownloadTask("Download_Task_2","param1","param2","param3")) //passing taskID
.add("Download_Task_3",new DownloadTask("Download_Task_3","param1","param2","param3")) //passing taskID
.add("Download_Task_4",new DownloadTask("Download_Task_4","param1","param2","param3")) //passing taskID
.add("Download_Task_5",new DownloadTask("Download_Task_5","param1","param2","param3")) //passing taskID
.add("Download_Task_6",new DownloadTask("Download_Task_6","param1","param2","param3")) //passing taskID
.add("Download_Task_7",new DownloadTask("Download_Task_7","param1","param2","param3")) //passing taskID
.add("Download_Task_8",new DownloadTask("Download_Task_8","param1","param2","param3")) //passing taskID
.execute();
This library also provides methods to implement pause,resume and stop the entire execution. Below is an example,
//For pausing further execution of the Queue
BackgroundTaskManager.pauseFurtherExecution();
//For resuming the execution if paused
BackgroundTaskManager.resumeExecution();
//Stop entire execution , cancelling all tasks and reclamation of all resources
BackgroundTaskManager.stopExecution();
Often we need to implement some UI code before and after execution of the background task. To enable this, we have implemented then() and before() inspired by promises in Javascript. This is how we can impplement that,
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.before(new Callable<String>() {
@Override
public String call() throws Exception {
//any UI logic needs to be executed just before processing the queue. like opening a progress dialog.
Toast.makeText(getApplicationContext(),"Execution Started",Toast.LENGTH_SHORT).show();
return null;
}
})
.add("Download_Task_1",new DownloadTask("Download_Task_1","param1","param2","param3"))
....
.add("Download_Task_8",new DownloadTask("Download_Task_8","param1","param2","param3"))
.then(new Callable<String>() {
@Override
public String call() throws Exception {
//any UI logic that needs to be executed after completion of the queue. like closing progress dialog.
Toast.makeText(getApplicationContext(),"Execution Complete",Toast.LENGTH_SHORT).show();
return null;
}
})
.execute();
This is how it works in a nutshell
Alternately, you can use AdvancedExecutorCallback for more control over executor events.
AdvancedExecutor.AdvancedExecutorCallback callback = new AdvancedExecutor.AdvancedExecutorCallback() {
@Override
public void onExecutionBegin() {
//Invoked just before execution starts
}
@Override
public void onExecutionpaused() {
//Invoked when execution paused
}
@Override
public void onExecutionResumed() {
//Invoked when execution resumes
}
@Override
public void onExecutionComplete() {
//Invoked when execution is complete
}
@Override
public void onExecutionCancelled() {
//Invoked when execution is cancelled
}
Then, set the callback in executor instance,
BackgroundTaskManager.getInstance(BackgroundTaskType.PARALLEL_PROCESSING)
.add("Download_Task_1",new DownloadTask("Download_Task_1","param1","param2","param3"))
...
.add("Download_Task_8",new DownloadTask("Download_Task_8","param1","param2","param3"))
.setCallback(callback)
.execute();
- Adding multiple Runnable by chaining and execution in a single line.
- Implement Serial and Parallel processing.
- Adding multiple tasks which return any result.
- Cancelling individual Tasks
- Pausing and resuming execution
- Handle errors and exception for individual tasks
- Callbacks for Execution events like onExecutionBegin, onExecutionComplete, onExecutionCancell
- adding then() and before() which is invoked after and before execution.
- Implementing seperate optimised background tasks for processes like Networking, I/O operations.
- Introducing ability to set any task as daemon.
To contribute to this project, follow these steps:
- Fork this repository.
- Create a branch:
git checkout -b <branch_name>
. - Make your changes and commit them:
git commit -m '<commit_message>'
- Push to the original branch:
git push origin <project_name>/<location>
- Create the pull request.
Alternatively see the GitHub documentation on creating a pull request.
Thanks to the following people who have contributed to this project:
- @jerrysjoseph π π»
If you want to contact me you can reach me at [email protected].
This project uses the following license: Apache-2.0.