https://betterprogramming.pub/managing-jetpack-compose-ui-state-with-sealed-classes-d864c1609279
https://github.com/nohjunh/Compose_SP/tree/main/UiState_Sealed_Classes
+class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
UistatewithsealedclassesTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
UiStateApp()
}
}
}
}
}
@Composable
fun UiStateApp() {
Surface(
color = MaterialTheme.colors.background,
modifier = Modifier.fillMaxSize()
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ContentScreen()
}
}
}
data class Album(
@DrawableRes val imageId: Int,
val title: String,
val description: String,
)
sealed class AlbumState {
object Loading : AlbumState()
data class Success(
val album: List<Album>
) : AlbumState()
object Error : AlbumState()
}
@Composable
fun ContentScreen(
viewModel: ContentViewModel = hiltViewModel()
) {
val albumState by viewModel.uiState.collectAsState()
Content(albumState)
}
@Composable
fun Content(
state: AlbumState
) {
Scaffold(
topBar = {
TopAppBar(
backgroundColor = Color.Transparent,
elevation = 0.dp,
) {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Default.ArrowBack,
contentDescription = "뒤로 가기"
)
}
}
}
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(it)
) {
when (state) {
is AlbumState.Loading -> LoadingScreen()
is AlbumState.Success -> ReadyScreen(albumList = state.album)
is AlbumState.Error -> ErrorScreen()
}
}
}
}
@HiltViewModel
class ContentViewModel @Inject constructor(
) : ViewModel(){
private val _uiState = MutableStateFlow<AlbumState>(AlbumState.Loading) // uiState의 처음은 Loading으로 시작 -> LoadingScreen이 보여짐.
val uiState = _uiState.asStateFlow()
init {
viewModelScope.launch {
delay(2000)
_uiState.value = AlbumState.Success(MockData) // uiState를 Success로 바꿔줌 -> ReadyScreen이 보여짐.
}
}
}
val MockData = listOf(
Album(
imageId = R.drawable.img1,
title = "테스트 이미지 1",
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor in venilamco laboris nisi ut aliquip ex ea commodo consequat. "
),
Album(
imageId = R.drawable.img2,
title = "테스트 이미지 2",
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magn "
),
Album(
imageId = R.drawable.img3,
title = "테스트 이미지 3",
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed diqua. Ut enim ad minim veniam, quis consequat. "
)
)
@Composable
fun ErrorScreen(
) {
}
@Composable
fun LoadingScreen(
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
Spacer(modifier = Modifier.weight(.2f))
Text("Loading Screen")
Spacer(modifier = Modifier.weight(.3f))
CircularProgressIndicator(
color = Color.Gray,
modifier = Modifier
.size(50.dp)
.padding(10.dp)
)
Spacer(modifier = Modifier.weight(.5f))
}
}
@Composable
fun ReadyScreen(
albumList: List<Album>
) {
Column(
modifier = Modifier.fillMaxSize()
) {
LazyColumn {
item {
Text(text = "Ready Screen")
}
items(albumList) { item ->
AlbumItem(item = item)
}
}
}
}
@Composable
fun AlbumItem(item: Album) {
Card(
elevation = 8.dp,
modifier = Modifier.padding(16.dp)
) {
Column(
modifier = Modifier.padding(5.dp)
) {
Image(painter = painterResource(id = item.imageId), contentDescription = "image")
Spacer(modifier = Modifier.padding(10.dp))
Text(
text = item.title,
style = MaterialTheme.typography.h4
)
Text(
text = item.description
)
}
}
}