model/User.kt
package com.example.myapplicationstate.model
data class User {
    val id: Int,
    val name: String
}
model/UiState.kt
package com.example.myapplicationstate.model
sealed class UiState {
    object Loading: UiState()
    data class Success(val users: List<User>): UiState()
    data class Error(val message: String): UiState()
}
種類	主な目的	特徴
sealed class	型の制限つき継承(状態分岐)	継承を制限し、when式で exhaustiveness(漏れなくチェック)できる
data class	データ保持専用クラス	自動で toString, equals, copy などが生成される
package com.example.myapplicationstate.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class UserViewModel : ViewModel(){
    private val _uiState = MutableStateFlow<UiState>(UiState.Loading)
    val uiState: StateFlow<UiState> = _uiSate
    init {
        fetchUsers()
    }
    fun fetchUsers(){
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            delay(2000)
            val  result = runCatching {
                getUsersFromApi()
            }
            _uiState.value =result.fold (
                onSuccess={ UiState.Success(it) },
                onFailure = { UiState.Error(it.message ?: "Unknown Error") }
            )
        }
    }
    private suspend fun getUsersFromApi(): List<User> {
        // 成功/失敗を切り替えるための仮コード
        if ((0..1).random() == 0) {
            throw RuntimeException("通信エラー")
        }
        return listOf(
            User(1, "Alice"),
            User(2, "Bob"),
            User(3, "Charlie")
        )
    }
}
ui/UserScreen.kt
package com.example.myapplicationstate.ui.screen
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.material.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import model.UiState
@Composable
fun UserScreen(userViewModel: UserViewModel = viewModel()) {
    val uiState by userViewModel.uiState.collectAsState()
    when (uiState){
        is UiState.Loading -> {
            Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        }
        is UiState.Success -> {
            val users = (uiState as UiState.Success).users
            LazyColumn {
                items(users) { user ->
                    Text(
                        text = user.name,
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(16.dp)
                    )
                }
            }
        }
        is UiState.Error -> {
            val message = (uiState as UiSatete.Error).message
            Column (
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text("エラー: $message", color = MaterialTheme.colors.error)
                Spacer(modifier = Modifier.height(16.dp))
                Button(onClick = { userViewModel.fetchUsers() }) {
                    Text("リトライ")
                }
            }
        }
    }
}
## @Composable
@Composable
fun Greeting(name: String) {
    Text(text = "Hello, $name!")
}
@Composable
fun MyScreen() {
    Column {
        Text("こんにちは")
        Button(onClick = { /* クリック処理 */ }) {
            Text("ボタン")
        }
    }
}
MainActivityはアプリの最初の画面
アプリのエントリーポイント
androidではuiとロジックが分けられるMVVMが一般的
 
					 
