import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CoroutineDispatcherDemo()
}
}
}
@Composable
fun CoroutineDispatcherDemo() {
val logs = remember { mutableStateListOf<String>() }
val scope = rememberCoroutineScope()
val scrollState = rememberScrollState()
fun logMessage(dispatcherName: String) {
val threadName = Thread.currentThread().name
logs.add("Running on $dispatcherName dispatcher, thread: $threadName")
}
Column(modifier = Modifier.fillMaxWidth()) {
Button(onClick = {
scope.launch(Dispatchers.IO) {
logMessage("IO")
}
}, modifier = Modifier.fillMaxWidth()) {
Text("Start IO Task")
}
Button(onClick = {
scope.launch(Dispatchers.Default) {
logMessage("Default")
}
}, modifier = Modifier.fillMaxWidth()) {
Text("Start Default Task")
}
Button(onClick = {
scope.launch(Dispatchers.Main) {
logMessage("Main")
}
}, modifier = Modifier.fillMaxWidth()) {
Text("Start Main Task")
}
Column(modifier = Modifier
.weight(1f, fill = false)
.verticalScroll(scrollState)) {
for (log in logs) {
Text(log)
}
}
}
}This solution uses rememberCoroutineScope() to get a scope tied to the composable lifecycle. Three buttons launch coroutines on different dispatchers: Dispatchers.IO for IO tasks, Dispatchers.Default for CPU-intensive tasks, and Dispatchers.Main for UI thread tasks.
Each coroutine appends a log message with the dispatcher name and current thread name to a mutableStateListOf, which updates the UI automatically. The logs are shown in a scrollable column so the user can see all messages.
This demonstrates how coroutines run on different threads depending on the dispatcher, and how to update UI safely from coroutines.