Skip to content

Commit

Permalink
added README & ResultOf
Browse files Browse the repository at this point in the history
  • Loading branch information
LavishSwarnkar committed Mar 29, 2022
1 parent 8d064c5 commit 742c355
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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<T>

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<T> class makes it easier to wrap these 2 possibilities in one.

[View examples & features](docs/ResultOf.md)
37 changes: 37 additions & 0 deletions commons/src/main/java/com/streamliners/commons/ResultOf.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.streamliners.commons

sealed class ResultOf<T>(val data: T? = null, val message: String? = null) {

class Success<T>(data: T) : ResultOf<T>(data)

class Error<T>(message: String) : ResultOf<T>(message = message)

fun onSuccess(handler: (T) -> Unit): ResultOf<T> {
if(this is Success)
data?.let(handler)
return this
}

fun onFailure(handler: (String) -> Unit): ResultOf<T> {
if(this is Error)
message?.let(handler)
return this
}

fun finally(handler: () -> Unit): ResultOf<T> {
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")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ abstract class Task<I, O> {
/**
* 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<I, O> {
Expand Down
100 changes: 100 additions & 0 deletions docs/ResultOf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# ResultOf<T>

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()
}
```
96 changes: 96 additions & 0 deletions docs/TasksInParallelHelper.md
Original file line number Diff line number Diff line change
@@ -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<A, B> =
object : Task<A, B>() {
override fun perform(input: A, listener: Listener<B>) {
// 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<B> =
object : TasksListener<B> {
override fun onSuccess(outputs: List<B>) {
// Do something with the outputs
}

override fun onFailure(error: String) {
// Show the error!
}
}
```

Step 4: Finally perform the tasks in parallel!

```kotlin
TasksInParallelHelper<A, B>()
.doTasksInParallel(inputs, task, listener)
```

---

## Java Example

Step 1: Prepare a list of inputs of any input type A

```kotlin
List<A> 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<A, B> task =
new Task<A, B>() {
@Override
public void perform(A input, @NonNull Listener<B> 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<B> listener =
new TasksInParallelHelper.TasksListener<B>() {
@Override
public void onSuccess(@NonNull List<? extends B> 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<A, B>()
.doTasksInParallel(inputs, task, listener);
```

0 comments on commit 742c355

Please sign in to comment.