Skip to main content

Dispatch

Simple CoroutineDispatcher injection

CoroutineDispatcher Injection

Change dispatchers without referencing a singleton or injecting a custom object. The dispatchers are a property of the CoroutineScope itself, so it's easy to inject custom dispatchers for testing.

Read more
fun updateUI() = coroutineScope.launchMain { /* ... */ }

val somethingDeferred = coroutineScope.asyncDefault { /* ... */ }

suspend fun fetchData() = withIO { /* ... */ }

val state = flow { /* ... */ }.flowOnIO()

Test Utilities

Dispatch's TestProvidedCoroutineScope is just aTestCoroutineScope under the hood, and every dispatcher is aTestCoroutineDispatcher. This means your tests can have granular control over every dispatcher without modifying production code.

Read more
@Test
fun someTest() = runBlocking {

val scope = TestProvidedCoroutineScope()
scope.pauseDispatcher()

// returns a Deferred<Data> using the "IO" dispatcher
val dataDeferred = SomeClass(scope).getDataFromNetwork()

dataDeferred.isCompleted shouldBe false

scope.resumeDispatcher()

dataDeferred.isCompleted shouldBe true

scope.cleanupTestCoroutines()
}

Better Android Lifecycle Awareness

Dispatch integrates with the Android lifecycle in a way similar to what thelifecycle-ktx library does, but with more extensibility. The resultant coroutineScopes all contain DispatcherProviders for easy integration with Espresso's IdlingResource system.

Read more
class MyFragment : Fragment() {

init {

// dispatchLifecycleScope is bound to the Fragment lifecycle
// withViewLifecycle creates a child scope each time the View is created
dispatchLifecycleScope.withViewLifecycle(this) {
myViewModel.dataFlow
.onEach { /* ... */ }
// starts and stops collection along with the view lifecycle
.launchOnStart()
}
}
}

Android Espresso

Dispatch will sync all coroutines with Espresso's IdlingRegistry, ensuring that Espresso waits until work is done before performing assertions.

Read more
// Retrieve the DispatcherProvider from a dependency graph,
// so that the same one is used throughout the codebase.
val customDispatcherProvider = testAppComponent.customDispatcherProvider

// Automatically register and unregister Dispatch's IdlingResource
@get:Rule val idlingRule = IdlingDispatcherProviderRule {
IdlingDispatcherProvider(customDispatcherProvider)
}

@Test
fun testThings() = runBlocking { /* ... */ }