Skip to content

Commit

Permalink
Implemented Cancelling of task
Browse files Browse the repository at this point in the history
  • Loading branch information
Bhuvaneshw committed Sep 3, 2023
1 parent 1420e79 commit c51d369
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 27 deletions.
54 changes: 43 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Task
Android Library for background and foreground tasks.<br>
Android Library for background and foreground tasks. Implemented with Thread.<br>
Do not start large number of Task concurrently.<br>
Starting large number of Threads may leads to out of memory.

### [For Kotlin check this](https://github.com/Bhuvaneshw/TaskKT)

Expand All @@ -17,7 +19,7 @@ allprojects {
Add the dependency
```
dependencies {
implementation 'com.github.Bhuvaneshw:task:1.1.3'
implementation 'com.github.Bhuvaneshw:task:1.1.4'
}
```

Expand All @@ -28,22 +30,31 @@ dependencies {

### Example
```
Task.with(task -> { //or new Task<>(task -> {
Task.with(task -> { //or new Task<>(task -> {
// Do some task
task.sleep(1000);
return null;
}).start();
```

### Example with Toast
```
Task.with(task -> { //or new Task<>(task -> {
Task.Foreground.start(() -> Toast.makeText(this, "This is how you can toast with Task", Toast.LENGTH_SHORT).show());
task.sleep(1000);
return null;
}).start();
```

Optional methods
1. onStart
2. onEnd
3. onResult
4. onError
5. doInBackground
6. doInForeground
7. then
1. onStart
2. onEnd
3. onResult
4. onError
5. doInBackground
6. doInForeground
7. then

### Complete Example
```
new Task<>(task -> {//Outer Task
Expand Down Expand Up @@ -77,6 +88,27 @@ new Task<>(task -> {//Outer Task
//NOTE: You should not call start method of chained task. It will be called by outer task when it is completed.
```

### Cancelling task
```
Task<?> task = Task.with(t -> {
int i = 10;
while (i-- > 0) {
t.ensureActive(); // Checks if the task is cancelled. If yes then moves to onCancel
t.publishProgress(i, "Running...");
t.sleep(500);
}
return "Hello";
})
.onStart(() -> textView.append("\n\n\nStarting Cancellable Task: Click here to cancel"))
.onEnd(() -> textView.append("\nTask Completed"))
.onProgress(p -> textView.append("\nTask Progress " + (10 - (int) p[0]) * 10 + "% " + p[1]))
.onResult(r -> textView.append("\nTask result " + r))
.onCancel(() -> textView.append("\nTask Cancelled"));
task.start();
textView.setOnClickListener(v -> task.cancel());
```

## For Java 1.7
Copy [these files](https://github.com/Bhuvaneshw/Task/tree/main/task/src/main/java/com/acutecoder/task) to your project
### Example
Expand Down
52 changes: 41 additions & 11 deletions app/src/main/java/com/acutecoder/taskdemo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public void run() {
Toast.makeText(MainActivity.this, "This is how you can toast with Task", Toast.LENGTH_SHORT).show(); // Toast in UI Thread
}
});
Thread.sleep(1000);
Thread.sleep(500);
return "T1";
}
})
Expand Down Expand Up @@ -75,15 +75,16 @@ public Task<?> run(String result) {
return new Task<>(new TaskRunnable<String>() {//Inner Task
@Override
public String run(Task<String> t2) throws Exception {
t2.sleep(2000);
t2.sleep(800);
t2.publishProgress("Result of outer task is " + result);
t2.sleep(2000);
t2.sleep(800);
return "Task 1 chained result";
}
}).onEnd(new TaskCallback() {
@Override
public void run() {
textView.append("\nChained task 1 finished");
startJ1_8Task(textView);
}
}).onProgress(new OnProgress() {
@Override
Expand All @@ -100,36 +101,65 @@ public void onResult(String result) {
})
.start();//this start method belongs to outer task and not inner task
//NOTE: You should not call start method of chained task. It will be called by outer task when it is completed.
}

@SuppressLint("SetTextI18n")
private void startJ1_8Task(TextView textView) {
//Java 1.8
Task.with(task -> {//Outer Task
Task.Foreground.start(() -> Toast.makeText(this, "This is how you can toast with Task", Toast.LENGTH_SHORT).show());
Task.Foreground.start(() -> Toast.makeText(MainActivity.this, "This is how you can toast with Task", Toast.LENGTH_SHORT).show());

task.sleep(1000);
task.sleep(500);
task.publishProgress(25);
task.sleep(1000) //Function chaining is also possible
task.sleep(500) //Function chaining is also possible
.publishProgress(56)
.sleep(2000)
.sleep(800)
.publishProgress(100)
.sleep(500);
return "T2";
})
.doInBackground() //or .doInForeground() # default it will be background task
.onStart(() -> textView.append("\nStarting task 2"))
.onStart(() -> textView.append("\n\n\nStarting task 2"))
.onEnd(() -> textView.append("\n" + "Task 2 Finished"))
.onResult(result -> textView.append("\nTask 2 " + result))
.onError(error -> textView.append("\nTask 2 " + error.getMessage()))
.onProgress(progress -> textView.append("\nTask 2 Progress " + progress[0]))
.then(result ->
new Task<>(t2 -> {//Inner Task
t2.sleep(2000);
t2.sleep(800);
t2.publishProgress("Result of outer task is " + result);
t2.sleep(2000);
t2.sleep(800);
return "Task 2 chained result";
}).onEnd(() -> textView.append("\nChained task 2 finished")
}).onEnd(() -> {
textView.append("\nChained task 2 finished");
startCancellableTask(textView);
}
).onProgress(progress -> textView.append("\nChained Task 2 Progress " + progress[0])
).onResult(result2 -> textView.append("\n" + result2)))
.start();//this start method belongs to outer task and not inner task
//NOTE: You should not call start method of chained task. It will be called by outer task when it is completed.
}

@SuppressLint("SetTextI18n")
private void startCancellableTask(TextView textView) {
//Cancelling of task
Task<?> task = Task.with(t -> {
int i = 10;
while (i-- > 0) {
t.ensureActive(); // Checks if the task is cancelled. If yes then moves to onCancel
t.publishProgress(i, "Running...");
t.sleep(500);
}
return "Hello";
})
.onStart(() -> textView.append("\n\n\nStarting Cancellable Task: Click here to cancel"))
.onEnd(() -> textView.append("\nTask Completed"))
.onProgress(p -> textView.append("\nTask Progress " + (10 - (int) p[0]) * 10 + "% " + p[1]))
.onResult(r -> textView.append("\nTask result " + r))
.onCancel(() -> textView.append("\nTask Cancelled"));
task.start();

textView.setOnClickListener(v -> task.cancel());
}

}
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '8.1.0' apply false
id 'com.android.library' version '8.1.0' apply false
id 'com.android.application' version '8.1.1' apply false
id 'com.android.library' version '8.1.1' apply false
}
2 changes: 1 addition & 1 deletion task/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ afterEvaluate {
from components.release
groupId = 'com.acutecoder'
artifactId = 'task'
version = '1.1.2'
version = '1.1.4'
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.acutecoder.task;

public class CancellationException extends RuntimeException {
public CancellationException() {
super("Task is cancelled");
}
}
50 changes: 48 additions & 2 deletions task/src/main/java/com/acutecoder/task/Task.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class Task<T> {
private final TaskRunnable<T> taskRunnable;
private TaskResult<T> taskResult;
private TaskError taskError;
private TaskCallback onStart, onEnd;
private boolean isBackground = true, isRunning = false;
private TaskCallback onStart, onEnd, onCancel;
private boolean isBackground = true, isRunning = false, isCancelled = false;
private OnProgress onProgress;
private NextTask<T> next;

Expand Down Expand Up @@ -76,6 +76,14 @@ public Task<T> onEnd(TaskCallback onEnd) {
return this;
}

/**
* Called when the execution of task is cancelled
*/
public Task<T> onCancel(TaskCallback onCancel) {
this.onCancel = onCancel;
return this;
}

/**
* Called to update progress (in UI) by publishProgress function in UI Thread
*/
Expand Down Expand Up @@ -105,6 +113,7 @@ public Task<T> doInForeground() {
*/
public void start() {
try {
isCancelled = false;
if (isRunning) throw new TaskException("Task already running!", isBackground);
isRunning = true;
if (isBackground) {
Expand All @@ -125,6 +134,16 @@ public void run() {
}
});
isRunning = false;
} catch (CancellationException e) {
isRunning = false;
if (onCancel != null) {
getForegroundHandler().post(new java.lang.Runnable() {
@Override
public void run() {
onCancel.run();
}
});
}
} catch (Exception e) {
isRunning = false;
if (onEnd != null)
Expand Down Expand Up @@ -157,6 +176,11 @@ public void run() {
isRunning = false;
if (onEnd != null) onEnd.run();
if (next != null) next.run(o).start();
} catch (CancellationException e) {
isRunning = false;
if (onCancel != null) {
onCancel.run();
}
} catch (Exception e) {
isRunning = false;
if (onEnd != null) onEnd.run();
Expand Down Expand Up @@ -206,6 +230,28 @@ public Task<T> then(NextTask<T> nextTask) {
return this;
}

/**
* Sets the cancellation flag
*/
public Task<T> cancel() {
isCancelled = true;
return this;
}

/**
* Returns state of task
*/
public boolean isActive() {
return !isCancelled;
}

/**
* Ensure task is alive (ie, task is not cancelled)
*/
public void ensureActive() {
if (!isActive()) throw new CancellationException();
}

private void onError(final Exception e) {
getForegroundHandler().post(new java.lang.Runnable() {
@Override
Expand Down

0 comments on commit c51d369

Please sign in to comment.