Skip to content

Commit

Permalink
Described scoping jobs and subscriptions in the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
arkivanov committed Jul 22, 2022
1 parent e545295 commit 7c3178f
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
121 changes: 121 additions & 0 deletions docs/component/scopes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Scoping jobs and subscriptions

Due to the fact that components are lifecycle-aware, it is very easy to manage coroutine scopes and reactive subscriptions.

## Creating a CoroutineScope in a component

```kotlin
fun CoroutineScope(context: CoroutineContext, lifecycle: Lifecycle): CoroutineScope {
val scope = CoroutineScope(context)
lifecycle.doOnDestroy(scope::cancel)
return scope
}

fun LifecycleOwner.coroutineScope(context: CoroutineContext): CoroutineScope =
CoroutineScope(context, lifecycle)

class SomeComponent(
componentContext: ComponentContext,
mainContext: CoroutineContext,
private val ioContext: CoroutineContext,
) : ComponentContext by componentContext {

// The scope is automatically cancelled when the component is destroyed
private val scope = coroutineScope(mainContext + SupervisorJob())

fun foo() {
scope.launch {
val result =
withContext(ioContext) {
"Result" // Result from background thread
}

println(result) // Handle the result on main thread
}
}
}
```

## Creating a CoroutineScope that survives Android configuration changes

```kotlin
internal class SomeRetainedInstance(mainContext: CoroutineContext) : InstanceKeeper.Instance {
// The scope survives Android configuration changes
private val scope = CoroutineScope(mainContext + SupervisorJob())

fun foo() {
scope.launch {
// Do the job
}
}

override fun onDestroy() {
scope.cancel() // Cancel the scope when the instance is destroyed
}
}

class SomeComponent(
componentContext: ComponentContext,
mainContext: CoroutineContext,
) : ComponentContext by componentContext {

private val someRetainedInstance = instanceKeeper.getOrCreate { SomeRetainedInstance(mainContext) }
}
```

## Creating a Reaktive DisposableScope in a component

```kotlin
fun DisposableScope(lifecycle: Lifecycle): DisposableScope {
val scope = DisposableScope()
lifecycle.doOnDestroy(scope::dispose)
return scope
}

fun LifecycleOwner.disposableScope(): DisposableScope =
DisposableScope(lifecycle)

class SomeComponent(
componentContext: ComponentContext,
) : ComponentContext by componentContext,
// The scope is automatically disposed when the component is destroyed
DisposableScope by componentContext.disposableScope() {

fun foo() {
singleFromFunction {
"Result" // Result from background thread
}
.subscribeOn(ioScheduler)
.observeOn(mainScheduler)
.subscribeScoped { // Subscribe using the DisposableScope
println(it) // Handle the result on main thread
}
}
}
```

## Creating a Reaktive DisposableScope that survives Android configuration changes

```kotlin
internal class SomeRetainedInstance : InstanceKeeper.Instance,
// The scope survives Android configuration changes
DisposableScope by DisposableScope() {

fun foo() {
completableFromFunction {
// Do the job
}.subscribeScoped()
}

override fun onDestroy() {
dispose() // Dispose the scope when the instance is destroyed
}
}

class SomeComponent(
componentContext: ComponentContext,
) : ComponentContext by componentContext {

private val someRetainedInstance = instanceKeeper.getOrCreate { SomeRetainedInstance() }
}
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ nav:
- State preservation: component/state-preservation.md
- Instance retaining: component/instance-retaining.md
- Back button: component/back-button.md
- Scoping jobs and subscriptions: component/scopes.md
- Custom ComponentContext: component/custom-component-context.md

- Child Stack:
Expand Down

0 comments on commit 7c3178f

Please sign in to comment.