Axolo Task Library
compile "com.github.AutSoft.AxoloTL:compiler-core:${axolotlVersion}"
compile "com.github.AutSoft.AxoloTL:tasklib:${axolotlVersion}"
compile "com.github.AutSoft.AxoloTL:tasklib-core:${axolotlVersion}"
compile "com.github.AutSoft.AxoloTL:tasklib-stetho:${axolotlVersion}"
testCompile "com.github.AutSoft.AxoloTL:tasklib-test:${axolotlVersion}"
annotationProcessor "com.github.AutSoft.AxoloTL:taskcompiler:${axolotlVersion}"
- Create a *Worker class
- Create a function in the Worker class with synchronous code
- Use
@CreateTaskannotation for the function - TaskLib compiler will create a Task for every function annotated with
@CreateTask- Every task class has the same parameters for the constructor as in the function which represented by the class
- The
getResult()function has the same return type as the function
publicclassSimpleWorker {
@CreateTaskpublicStringfirst(intparameter) {
return"Result: " + parameter;
}
}- Create a
TaskEngineHolderwhere you would like to use the task (inside in an activity, fragment, etc.) - Execute the task with the executeTask function of the TaskEngineHolder
publicclassSampleTaskFragmentextendsFragment {
TaskEngineHolderholder;
publicSampleTaskFragment() {
holder = newTaskEngineHolder(this);
}
@OverridepublicvoidonResume() {
super.onResume();
holder.start();
holder.executeTask(newFirstTask(3));
}
@OverridepublicvoidonPause() {
super.onPause();
holder.stop();
}
publicvoidonTaskResult(FirstTasktask) {
if(!task.hasError()) {
// Handle resultStringresult = task.getResult();
} else {
// Handle error...
}
}
}For MVP, sample presenter:
publicabstractclassPresenter<S> {
protectedSscreen;
privateTaskEngineHolderholder = newTaskEngineHolder(this);
@CallSuperpublicvoidattachScreen(Sscreen) {
this.screen = screen;
holder.start();
}
@CallSuperpublicvoiddetachScreen() {
this.screen = null;
holder.stop();
}
publicvoidstartFirstTask() {
holder.executeTask(newFirstTask);
}
publicvoidonTaskResult(FirstTasktask) {
if(!task.hasError()) {
// Handle resultStringresult = task.getResult();
} else {
// Handle error...
}
}
}holder.executeTask(newFirstTask(3), , newInlineTaskListener<String, Void>() {
@OverridepublicvoidonTaskResult(BaseTask<String, Void> task) {
// handle task result...
}
});In the worker function you can throw any RuntimeException.
If any exception thrown, then the task.hasError() function will return true.
With the task.getException() function you can get the thrown exception in the task result function.
Function in worker:
@CreateTaskpublicvoidtaskWithError() {
thrownewTaskException(ERROR_CODE_INTEGER);
}Callback:
publicvoidonTaskResult(TaskWithErrorTasktask) {
task.hasError(); // returns truetask.getErrorCode(); // returns ERROR_CODE_INTEGER
}You can pass any error object with the TaskException:
@CreateTaskpublicvoidtaskWithError() {
thrownewTaskException(ERROR_CODE_INTEGER, newCustomObject());
}In the callback function use getErrorObject() function:
publicvoidonTaskResult(TaskWithErrorTasktask) {
task.hasError(); // returns truetask.getErrorCode(); // returns ERROR_CODE_INTEGERtask.getErrorObject(); // returns the created CustomObject
}In the worker function you can use a TaskAgent as a first argument (it is only allowed in the first place).
With a TaskAgent instance (which is created and passed by the Task Library) you can send progress updates to the caller.
publicclassProgressWorker {
@CreateTaskpublicStringlongRunning(TaskAgent<String> agent, intparameter) {
intmax = 10;
for (inti = 0; i < max; i++) {
intpercent = (int) ((100.0 * i) / max);
agent.publishProgress("PROGRESS: " + percent + "%");
Thread.sleep(300); // some long-running synch work
}
agent.publishProgress("PROGRESS: 100%");
return"DONE: " + parameter;
}
}In the target object you can define an onTaskProgress function with two argument.
One for the task and one for the progress object:
protectedvoidonTaskProgress(LongRunningTasktask, Stringprogress) {
// setProgress("onTaskProgress: " + progress);
}Global task exception is similar to the simple task exception. The main difference is that you can handle global errors in any target which is held by a TaskEngineHolder:
publicbooleanonTaskGlobalError(GlobalErrorerror) {
if (error.getErrorCode() == SOME_CODE) {
// handle global errorreturntrue;
}
returnfalse;
}TaskLib try to call the onTaskGlobalError method in the target which is executed the task with global error. If it is unsuccessful or the error is not handled then it will call the other targets in unspecified order. If any onTaskGlobalError method returns true then the global error is handled and there won't be any effect of the execution of the task (no onTaskResult or other call). If non of the onTaskGlobalError method returns true then the global task exception is handled like it was a simple task exception (onTaskResult call with hasError and errorCode).
FIXME
The @CreateTask annotation has a value parameter to specify which scheduler you want to use for running the task.
public class CustomSchedulersWorker {
@CreateTask(TaskSchedulers.IO)
public void customSchedulerIo() {
// do some work...
}
@CreateTask(MyCustomSchedulers.MY_SCHEDULER)
public void fullCustomScheduler() {
// do some work...
}
}
In TaskSchedulers there are some basic scheduler which comes from RxJava:
- SINGLE
- COMPUTATION
- IO
- TRAMPOLINE
- NEW_THREAD
If you need a custom scheduler you can register it with a positive integer id and you can use this id in @CreateTask annotation.
TaskSchedulers.registerScheduler(MyCustomSchedulers.MY_SCHEDULER, Schedulers.newThread());For dagger injection you have to annotate your injector static instance with hu.axolotl.tasklib.annotation.Injector annotation.
@InjectorpublicstaticAppComponentinjector;In the AppComponent interface you have to declare a new method for the helpers of each worker. For example if you have a ProfileWorker then the lib will generate a ProfileWorkerTaskHelper class, so you have to add:
voidinject(FriendsWorkerTaskHelperfriendsWorkerTaskHelper);publicclassRxTasksWorker {
@CreateTaskpublicFlowable<String> flowable() {
returnFlowable.just("Flowable done!");
}
@CreateTaskpublicObservable<String> observable() {
returnObservable.just("Observable done!");
}
@CreateTaskpublicSingle<String> single() {
returnSingle.just("Single done!");
}
@CreateTaskpublicCompletablecompletable() {
returnCompletable.complete();
}
}FIXME
FIXME
FIXME
- Foreground service support for workers: So you can use executeTask to start a foreground service with given icon, name, etc.
Copyright 2017 AutSoft Kft.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.