Coroutines Channel Example
This tutorial will show you how to use a Kotlin Channel rather than LiveData or StateFlow. This is for purposes where you need to send only a one-time event. If you use LiveData or StateFlow and for example the configuration changes, the event gets raised again. However with Kotlin Channels you can send only a one-time event.
[lwtoc]
What is a Channel?
According to Kotlin documentation, a Channel is a non-blocking primitive for communication between a sender (via SendChannel) and a receiver (via ReceiveChannel). Conceptually, a channel is similar to Java's java.util.concurrent.BlockingQueue, but it has suspending operations instead of blocking ones and can be closed.
Read more here.
Let's look at an example with Android.
Example 1: Kotlin Android Coroutines Channel Example
A simple beginner friendly example. Here are what you will learn from this example:
- Kotlin Coroutines
- Viewmodel
- Channel
- Flow
- ViewBinding
Here are the demo images of the created project:
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
In your app/build.gradle
add the following dependencies:
// coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
// viewmodel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// lifecycle
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
// activity ktx for viewmodel
implementation "androidx.activity:activity-ktx:1.1.0"
Step 3: Enable Java8 and ViewBinding
In the same app/build.gradle
enable Java8 and Viewbinding as follows inside the android{}
closure:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
Step 4: Design Layout
Place a MaterialButton inside your activity_main.xml
as follows:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/parent_layout"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.button.MaterialButton
android:id="@+id/show_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/show_snackbar"
app:elevation="10dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Step 5: Create ViewModel
Create the MainViewModel.kt
and add the following imports:
import android.content.res.Resources
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
Extend the ViewModel
class:
Create a private event channel:
and event an event flow:
Trigger a fake call:
fun triggerEvent(res: Resources) = viewModelScope.launch {
eventChannel.send(MainEvent.ErrorEvent(res.getString(R.string.error)))
}
Here is the full code:
MainViewModel.kt
import android.content.res.Resources
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
class MainViewModel : ViewModel() {
// create channel ! do not expose to fragment or activity
private val eventChannel = Channel<MainEvent> { }
// so receive it as flow
val eventFlow = eventChannel.receiveAsFlow()
// fake call
fun triggerEvent(res: Resources) = viewModelScope.launch {
eventChannel.send(MainEvent.ErrorEvent(res.getString(R.string.error)))
}
sealed class MainEvent {
data class ErrorEvent(val message: String) : MainEvent()
}
}
Step 5: MainActivity
In the MainActivity, when the MaterialButton is clicked we will trigger the simulated call. Here is the full code:
MainActivity.kt
import android.content.res.Resources
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
class MainViewModel : ViewModel() {
// create channel ! do not expose to fragment or activity
private val eventChannel = Channel<MainEvent> { }
// so receive it as flow
val eventFlow = eventChannel.receiveAsFlow()
// fake call
fun triggerEvent(res: Resources) = viewModelScope.launch {
eventChannel.send(MainEvent.ErrorEvent(res.getString(R.string.error)))
}
sealed class MainEvent {
data class ErrorEvent(val message: String) : MainEvent()
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |