diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..923654d --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# AndroidCommons + +Android library with common utilities required when building Android apps. + +--- + +## Usage + +Step 1: Add JitPack in your **root build.gradle** : + +```groovy + allprojects { + repositories { + ... + maven { url 'https://jitpack.io' } + } + } +``` + +Step 2: Add AndroidCommons dependency to your **app build.gradle**: + +```groovy + dependencies { + implementation 'com.github.The-Streamliners:AndroidCommons:0.1.0' + } +``` + +--- + +## Utilities + +### TasksInParallelHelper + +TasksInParallelHelper is a helper class that performs task in parallel. Any input type (I) & output type (O) is supported. By Implementing task class, you can perform any task on I to generate O, whether it be a long IO operation or a network call. + +[View examples](docs/TasksInParallelHelper.md) + +--- + +### ResultOf + +ResultOf is a resource wrapper class. While performing an IO / Network operation, there are 2 possibilities: + +- Task will be successful & we will get some data T + +- Task may fail producing some exception + + +ResultOf class makes it easier to wrap these 2 possibilities in one. + +[View examples & features](docs/ResultOf.md) \ No newline at end of file diff --git a/commons/src/main/java/com/streamliners/commons/ResultOf.kt b/commons/src/main/java/com/streamliners/commons/ResultOf.kt new file mode 100644 index 0000000..7b111fa --- /dev/null +++ b/commons/src/main/java/com/streamliners/commons/ResultOf.kt @@ -0,0 +1,37 @@ +package com.streamliners.commons + +sealed class ResultOf(val data: T? = null, val message: String? = null) { + + class Success(data: T) : ResultOf(data) + + class Error(message: String) : ResultOf(message = message) + + fun onSuccess(handler: (T) -> Unit): ResultOf { + if(this is Success) + data?.let(handler) + return this + } + + fun onFailure(handler: (String) -> Unit): ResultOf { + if(this is Error) + message?.let(handler) + return this + } + + fun finally(handler: () -> Unit): ResultOf { + handler() + return this + } + + fun await(): T { + if(this is Success) + data?.let { + return it + } ?: throw Exception("Something went wrong") + else + message?.let { + throw Exception(it) + } ?: throw Exception("Something went wrong") + } + +} \ No newline at end of file diff --git a/commons/src/main/java/com/streamliners/commons/tasksInParallel/TasksInParallelHelper.kt b/commons/src/main/java/com/streamliners/commons/tasksInParallel/TasksInParallelHelper.kt index dc7c2ea..ef88e0e 100644 --- a/commons/src/main/java/com/streamliners/commons/tasksInParallel/TasksInParallelHelper.kt +++ b/commons/src/main/java/com/streamliners/commons/tasksInParallel/TasksInParallelHelper.kt @@ -20,7 +20,7 @@ abstract class Task { /** * TasksInParallelHelper is a helper class that performs task in parallel. * Any input type (I) & output type (O) is supported. - * By Implementing task class, you can perform ny task on I to generate O. + * By Implementing task class, you can perform any task on I to generate O. * Whether it be a long IO operation or a network call. */ class TasksInParallelHelper { diff --git a/docs/ResultOf.md b/docs/ResultOf.md new file mode 100644 index 0000000..79eeffb --- /dev/null +++ b/docs/ResultOf.md @@ -0,0 +1,100 @@ +# ResultOf + +ResultOf is a resource wrapper class. While performing an IO / Network operation, there are 2 possibilities: + +- Task will be successful & we will get some data T + +- Task may fail producing some exception + + +ResultOf class makes it easier to wrap these 2 possibilities in one. + +--- + +## Code without ResultOf class + +You'll have to use try catch whenever calling a suspending function + +```kotlin +try { + val user = userRepository.getUser() +} catch(e: Exception) { + // Handle error +} + + +OR + + +coroutineScope.launch(exceptionHandler) { + val user = userRepository.getUser() +} +``` + +## Using ResultOf class with when block + +```kotlin +when( + val result = userRepository.getUser() +) { + is Success -> { + val user = result.data + // Consume result + } + is Error -> { + val error = result.message + // Show error + } +} +``` + +The code might look longer, but there are 2 functions at rescue : + +## Using ResultOf with onSuccess & onFailure + +```kotlin +userRepository.getUser() + .onSuccess { user -> + + }.onFailure { error -> + + } +``` + +But these functions lead to callback hell when calling multiple suspending functions in a sequence: + +## Callback hell + +```kotlin +userRepository.getUser() + .onSuccess { user -> + paymentsRepository.getPayments(user) + .onSuccess { payments -> + + }.onFailure { error -> + + } + }.onFailure { error -> + + } +``` + +Is there a way out? Of course, ResultOf class offers await() method : + +## Using ResultOf class with await() + +```kotlin +try { + val user = userRepository.getUser().await() + val payments = paymentsRepository.getPayments(user).await() +} catch(e: Exception) { + // Handle error +} + +OR + +coroutineScope.launch(exceptionHandler) { + val user = userRepository.getUser().await() + val payments = paymentsRepository.getPayments(user).await() +} +``` \ No newline at end of file diff --git a/docs/TasksInParallelHelper.md b/docs/TasksInParallelHelper.md new file mode 100644 index 0000000..7830796 --- /dev/null +++ b/docs/TasksInParallelHelper.md @@ -0,0 +1,96 @@ +# TasksInParallelHelper + +TasksInParallelHelper is a helper class that performs task in parallel. Any input type (I) & output type (O) is supported. By Implementing task class, you can perform any task on I to generate O, whether it be a long IO operation or a network call. + +--- + +## Kotlin example + +Step 1: Prepare a list of inputs of any input type A + +```kotlin +val inputs = listOf(A(1), A(2), A(3)) +``` + +Step 2: Implement Task class to transform input type A into output type B + +```kotlin +val task: Task = + object : Task() { + override fun perform(input: A, listener: Listener) { + // Simple stupid task that converts int to String + val output = B(input.x.toString()) + listener.onSuccess(output) + } + } +``` + +Step 3: Implement listener to get outputs of output type B + +```kotlin +val listener: TasksListener = + object : TasksListener { + override fun onSuccess(outputs: List) { + // Do something with the outputs + } + + override fun onFailure(error: String) { + // Show the error! + } + } +``` + +Step 4: Finally perform the tasks in parallel! + +```kotlin +TasksInParallelHelper() + .doTasksInParallel(inputs, task, listener) +``` + +--- + +## Java Example + +Step 1: Prepare a list of inputs of any input type A + +```kotlin +List inputs = Arrays.asList(new A(1), new A(2), new A(3)); +``` + +Step 2: Implement Task class to transform input type A into output type B + +```kotlin +Task task = + new Task() { + @Override + public void perform(A input, @NonNull Listener listener) { + // Simple stupid task that converts int to String + B output = new B(String.valueOf(input.getX())); + listener.onSuccess(output); + } + }; +``` + +Step 3: Implement listener to get outputs of output type B + +```kotlin +TasksInParallelHelper.TasksListener listener = + new TasksInParallelHelper.TasksListener() { + @Override + public void onSuccess(@NonNull List outputs) { + // Do something with the outputs + } + + @Override + public void onFailure(@NonNull String error) { + // Show the error! + } + }; +``` + +Step 4: Finally perform the tasks in parallel! + +```kotlin +new TasksInParallelHelper() + .doTasksInParallel(inputs, task, listener); +``` \ No newline at end of file