import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: android.os.Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val viewModel = GreetingViewModel()
GreetingScreen(viewModel)
}
}
}
// UseCase class that simulates fetching a greeting message
class FetchGreetingUseCase {
suspend operator fun invoke(): String {
delay(1000) // simulate network or computation delay
return "Hello from Use Case!"
}
}
// ViewModel that uses the UseCase and exposes UI state
class GreetingViewModel : ViewModel() {
private val useCase = FetchGreetingUseCase()
var greeting by mutableStateOf("")
private set
var isLoading by mutableStateOf(false)
private set
fun fetchGreeting() {
viewModelScope.launch {
isLoading = true
greeting = useCase()
isLoading = false
}
}
}
@Composable
fun GreetingScreen(viewModel: GreetingViewModel) {
val greeting = viewModel.greeting
val isLoading = viewModel.isLoading
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = "Greeting:", style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(8.dp))
TextField(
value = greeting,
onValueChange = {},
readOnly = true,
modifier = Modifier.fillMaxWidth(),
placeholder = { Text("[__________________]") },
singleLine = true
)
Spacer(modifier = Modifier.height(16.dp))
if (isLoading) {
CircularProgressIndicator()
} else {
Button(onClick = { viewModel.fetchGreeting() }) {
Text("Fetch Greeting")
}
}
}
}
This example shows a simple Use Case pattern in Android with Kotlin and Jetpack Compose.
The FetchGreetingUseCase class simulates a task that takes time, like fetching data from the internet, by delaying for 1 second and then returning a greeting string.
The GreetingViewModel holds the UI state: the greeting text and a loading flag. It calls the Use Case inside a coroutine to keep the UI responsive.
The GreetingScreen composable displays the greeting in a read-only text field, shows a loading spinner while waiting, and has a button to start fetching the greeting.
This pattern separates business logic (Use Case) from UI logic (ViewModel and Composable), making the code easier to test and maintain.