Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ErrorxCode committed Apr 27, 2022
1 parent ae23fb3 commit a9b0374
Show file tree
Hide file tree
Showing 11 changed files with 583 additions and 0 deletions.
8 changes: 8 additions & 0 deletions AsyncTask/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
plugins {
id 'java-library'
}

java {
sourceCompatibility = JavaVersion.VERSION_16
targetCompatibility = JavaVersion.VERSION_16
}
162 changes: 162 additions & 0 deletions AsyncTask/src/main/java/com/xcoder/tasks/AsyncTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package com.xcoder.tasks;

import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
* AsyncTask is a convenience class for running asynchronous tasks.
* This is java port of google play services Tasks api. This can be used in both android
* and non-android projects. However, in android , targetSdkVersion should be >= 28.
*
* @param <T> The type of the result.
*/
public class AsyncTask<T> {
public Exception exception;
public T result;
public boolean isSuccessful;
private CompletableFuture<T> future;
private OnCompleteCallback<T> completeCallback = call -> {};
private OnErrorCallback errorCallback = e -> {};
private OnSuccessCallback<T> successCallback = result -> {};

/**
* Executes the task asynchronously. This method returns immediately. It takes a callable which
* if returns the value, the task is considered successful. If the callable throws an exception,
* the task is considered failed.
*
* @param callable the task to execute
* @param <T> the type of the result
* @return the call that can be used to get the result in future
*/
public static <T> AsyncTask<T> callAsync(Callable<T> callable) {
AsyncTask<T> call = new AsyncTask<>();
call.future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(10);
return callable.call();
} catch (Exception e) {
throw new CompletionException(e);
}
}).whenComplete((t, throwable) -> {
if (throwable == null) {
call.result = t;
call.isSuccessful = true;
call.successCallback.onSuccess(t);
} else {
call.exception = (Exception) throwable;
call.isSuccessful = false;
call.errorCallback.onError((Exception) throwable);
}
call.completeCallback.onComplete(call);
});
return call;
}

/**
* Joins all the tasks and build a single task that is resultant of all the tasks.
*
* @param tasks the tasks to join
* @return the joined task
*/
public static AsyncTask<?> allOf(AsyncTask<?>... tasks) {
AsyncTask<?> task = new AsyncTask<>();
CompletableFuture<?>[] array = Arrays.stream(tasks)
.map((Function<AsyncTask<?>, CompletableFuture<?>>) asyncTask -> asyncTask.future)
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(array).whenComplete((unused, throwable) -> {
task.completeCallback.onComplete(null);
if (throwable == null) {
task.isSuccessful = true;
task.successCallback.onSuccess(null);
} else {
task.exception = (Exception) throwable;
task.isSuccessful = false;
task.errorCallback.onError((Exception) throwable);
}
});
return task;
}

/**
* Executes the task asynchronously and sequentially one after another. If you have multiple nested tasks,
* you can use this method to execute them sequentially.
* @param function the function to execute
* @param <R> the type of the result
* @return the call that can be used to get the result in future
*/
public <R> AsyncTask<R> thenPerform(AsyncFunction<T, R> function) {
AsyncTask<R> task = new AsyncTask<>();
task.future = future.thenApplyAsync(t -> {
try {
return function.task(t);
} catch (Exception e) {
throw new CompletionException(e);
}
}).whenComplete((r, throwable) -> {
if (throwable == null) {
task.result = r;
task.isSuccessful = true;
task.successCallback.onSuccess(r);
} else {
task.exception = (Exception) throwable;
task.isSuccessful = false;
task.errorCallback.onError((Exception) throwable);
}
task.completeCallback.onComplete(task);
});
return task;
}

/**
* Returns the result of the task or wait if it is not yet completed.
*
* @param timeoutSeconds the maximum time (in seconds) to wait for the task to complete
* @return The result
* @throws Exception if the task failed or the timeout was reached.
*/
public T getResult(int timeoutSeconds) throws Exception {
return future.get(timeoutSeconds, TimeUnit.SECONDS);
}


public AsyncTask<T> setOnSuccessCallback(OnSuccessCallback<T> onSuccessCallback) {
this.successCallback = onSuccessCallback;
return this;
}

public AsyncTask<T> setOnErrorCallback(OnErrorCallback onErrorCallback) {
this.errorCallback = onErrorCallback;
return this;
}

public void setOnCompleteCallback(OnCompleteCallback<T> onCompleteCallback) {
this.completeCallback = onCompleteCallback;
}


public interface OnCompleteCallback<T> {
void onComplete(AsyncTask<T> call);
}

public interface OnSuccessCallback<T> {
void onSuccess(T result);
}

public interface OnErrorCallback {
void onError(Exception e);
}

/**
* A function used to perform an asynchronous task in chain. To be used with {@link #thenPerform(AsyncFunction)} method
* @param <T> the type of the input
* @param <R> the type of the output
*/
@FunctionalInterface
public interface AsyncFunction<T,R> {
R task(T t) throws Exception;
}
}
29 changes: 29 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.android.tools.build:gradle:7.1.1'
classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:0.14.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
mavenCentral()
maven {
url 'https://jitpack.io'
}
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}
18 changes: 18 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
android.enableJetifier=true
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#Sun Feb 06 00:06:22 IST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Loading

0 comments on commit a9b0374

Please sign in to comment.