Task Handling library for Kotlin and Android.
This library is based on Kotlin Coroutine and Thread
Why CoTask
- Pause CoTask
- Resume CoTask
- Publish progress to main thread
- Error handling and Other callbacks
Contents:
1. Setup
1.1 Kotlin DSL
1.2 Groovy DSL
2. Usage
2.1 CoTask (Recommended)
2.2 ThreadTask
2.3 JTask
3. License
Step 1: Project level build.gradle / settings.gradle
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven { url = uri("https://jitpack.io") } } }
Step 2: Module level build.gradle
dependencies { implementation("com.github.Bhuvaneshw.task:$module:$version") }
Replace $module with cotask, threadtask or jtask
Replace $version with latest version
Latest Version:
Example:
dependencies { implementation("com.github.Bhuvaneshw.task:cotask:2.0.0") implementation("com.github.Bhuvaneshw.task:threadtask:2.0.0") implementation("com.github.Bhuvaneshw.task:jtask:2.0.0") }
Step 1: Project level build.gradle / settings.gradle
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() maven { url 'https://jitpack.io' } } }
Step 2: Module level build.gradle
dependencies { implementation 'com.github.Bhuvaneshw.task:$module:$version' }
Simple CoTask
CoTask { // Default dispatcher will be Dispatchers.Default delay(1000) // Your expensive task }
Using Coroutine Functions
CoTask { // Task<Unit,Nothing>:CoroutineScope delay(1000) launch { // from coroutine library delay(1000) } val job = async { // from coroutine library delay(1000) } job.await() }
Using Dispatcher
CoTask(Dispatchers.IO) { delay(1000L) } // Extensions CoTask withIO { } // or CoTask.withIO { }
Callbacks
CoTask { // this: Task<String, Nothing> String => return type delay(1000) "My valuable result" }.onPause { appendStatus("CoTask1 Paused") }.onResume { appendStatus("CoTask1 Resumed") }.onEnd { appendStatus("CoTask1 completed") }.onCancelled { appendStatus("CoTask1 cancelled") }.onResult { result: String -> appendStatus("CoTask1 result $result") }
Error Handling
CoTask { delay(4000) 5 / 0 // Divide by zero }.catch { appendStatus("CoTask error $it") } // Or CoTask { delay(4000) 5 / 0 // Divide by zero }.logError("CoTask")
Chaining Tasks
CoTask { // this: Task<String, Nothing> String => return type delay(1000) "500" }.then { it: String -> // this: Task<Int, Nothing>, it:String => the previous return value delay(2000) it.toInt() }.then { it: Int -> it / 5f }.onResult { result: Float -> appendStatus("CoTask2 result $result") }
Progressed CoTask
ProgressedCoTask { // this: Task<String, Int> String => return type, Int => Progress Type delay(1000) publishProgress(50) delay(1000) publishProgress(99) "My valuable result" }.onProgress { progress: Int -> appendStatus("CoTask3 progress $progress") }.onResult { result: String -> appendStatus("CoTask3 result $result") }
Cancelling Task
val task = ProgressedCoTask { var i = 10 while (i-- > 0) { ensureActive() // enabling that the task can be paused/cancelled here publishProgress(10 - i) } }.onProgress { appendStatus("CoTask4 progress $it") }.onCancelled { appendStatus("CoTask4 cancelled") } // Cancelling the task after 1.5 seconds CoTask { delay(1500) task.cancel() }
Pausing and Resuming
val task = ProgressedCoTask { var i = 10 while (i-- > 0) { ensureActive() // enabling that the task can be paused/cancelled here publishProgress(10 - i) } // launchPausing { }.pause() // asyncPausing { }.pause() }.onProgress { appendStatus("CoTask5 progress $it") }.onPause { appendStatus("CoTask5 paused") }.onResume { appendStatus("CoTask5 resumed") } // Pausing and Resuming the task after 1.5 seconds of break CoTask { delay(1500) task.pause() delay(1500) task.resume() }
Startable Tasks
StartableCoTask { delay(1000) }.onStart { }.start() StartableProgressedCoTask { publishProgress(10) delay(1000) publishProgress(100) }.start() // If you return any data, then StartableCoTask { delay(1111) "My value" }.start { result: String -> // called before on result callback appendStatus("Result $result") }
Using with scopes, Extension functions
// You can use these extensions functions with coroutine scope GlobalScope.coTask { } GlobalScope.progressedCoTask { publishProgress(0) } GlobalScope.startableCoTask { } GlobalScope.startableProgressedCoTask { publishProgress(0) } // Specifying Dispatcher GlobalScope.coTask(Dispatchers.IO) { } GlobalScope.progressedCoTask(Dispatchers.IO) { publishProgress(0) } GlobalScope.startableCoTask(Dispatchers.IO) { } GlobalScope.startableProgressedCoTask(Dispatchers.IO) { publishProgress(0) } // "with" infix notation CoTask withIO { } ProgressedCoTask withIO { publishProgress(1) } // "with" can't be used as infix notation if you are accessing other functions like start, onCancel, logError, etc StartableCoTask.withIO { }.start() CoTask.withIO { }.logError()
Note: Pausing and Resuming is not available in ThreadTask
Simple Thread Task
ThreadTask { delay(1000) // Your expensive task }
Callbacks
ThreadTask { // this: Task<String, Nothing> String => return type delay(1000) "My valuable result" }.onEnd { appendStatus("ThreadTask1 completed") }.onCancelled { appendStatus("ThreadTask1 cancelled") }.onResult { result: String -> appendStatus("ThreadTask1 result $result") }
Error Handling
ThreadTask { delay(4000) 5 / 0 // Divide by zero }.catch { appendStatus("ThreadTask error $it") } // Or ThreadTask { delay(4000) 5 / 0 // Divide by zero }.logError("ThreadTask")
Chaining Tasks
ThreadTask { // this: Task<String, Nothing> String => return type delay(1000) "500" }.then { it: String -> // this: Task<Int, Nothing>, it:String => the previous return value delay(2000) it.toInt() }.then { it: Int -> it / 5f }.onResult { result: Float -> appendStatus("ThreadTask2 result $result") }
ProgressedThreadTask
ProgressedThreadTask { // this: Task<String, Int> String => return type, Int => Progress Type delay(1000) publishProgress(50) delay(1000) publishProgress(99) "My valuable result" }.onProgress { progress: Int -> appendStatus("ThreadTask3 progress $progress") }.onResult { result: String -> appendStatus("ThreadTask3 result $result") }
Cancelling Task
val task = ProgressedThreadTask { var i = 1 while (i <= 100) { publishProgress(i) ensureActive() // Mandatory for ThreadTask to check for cancellation and calling onCancelled callback delay(1000) i += 10 } }.onProgress { appendStatus("ThreadTask4 progress $it") }.onCancelled { appendStatus("ThreadTask4 cancelled") } // Cancelling the task after 1.5 seconds ThreadTask { delay(1500) task.cancel() }
Startable Tasks
StartableThreadTask { delay(1000) }.onStart{ }.start() StartableProgressedThreadTask { publishProgress(10) delay(1000) publishProgress(100) }.start() // If you return any data, then StartableThreadTask { delay(1111) "My value" }.start { result: String -> // called before on result callback appendStatus("Result $result") }
Simple JTask
JTask.with(task -> { task.sleep(1000); return "hello"; }).start();
Callbacks and Error handling
JTask.with(task -> { int i = 0; while (i < 10) { task.ensureActive(); // Mandatory if you cancel the task! task.publishProgress((i + 1) * 10); i++; } return "hello"; }).onStart(() -> { log("OnStart"); }).onEnd(() -> { log("OnEnd"); }).onCancel(() -> { log("OnCancel"); }).onError((error) -> { log("OnError : " + error.getLocalizedMessage()); }).onProgress((progress) -> { log("Progress: " + ((int) progress[0])); }).onResult((result) -> { log("Result: " + result); }).start();
Chaining Tasks
new JTask<String>(task -> { task.sleep(1000); return "123"; }).then(result -> new JTask<Integer>(task -> { task.sleep(1000); return Integer.parseInt(result); }).onStart(() -> { log("OnStart"); }).onResult(intResult -> { log("Result: " + intResult); }) ).start();
Cancelling Task
JTask<?> task = JTask.with(t -> { int i = 0; while (i < 10) { t.ensureActive(); // Mandatory if you cancel the task! t.publishProgress((i + 1) * 10); i++; } return "hello"; }).onCancel(() -> { log("OnCancel"); }); task.start(); new Timer().schedule(new TimerTask() { @Override public void run() { task.cancel(); } }, 1000);
Task - Task Handling Library
Copyright (C) 2024 Bhuvaneshwaran
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.