Skip to content

Commit

Permalink
[Ref]#11 Home Di,MVI패턴 적용
Browse files Browse the repository at this point in the history
  • Loading branch information
angryPodo committed Dec 16, 2024
1 parent cad627b commit 0724052
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.sopt.and.presentation.home

sealed interface HomeEffect {
data class ShowError(val message: String) : HomeEffect
data object NavigateToDetail : HomeEffect
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.sopt.and.presentation.home

sealed interface HomeIntent {
data object LoadInitialData : HomeIntent
data object RefreshContent : HomeIntent
}
63 changes: 42 additions & 21 deletions app/src/main/java/org/sopt/and/presentation/home/HomeScreen.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package org.sopt.and.presentation.home

import android.app.Activity
import android.widget.Toast
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import org.sopt.and.presentation.home.component.BannerView
import org.sopt.and.presentation.home.component.EditorPicksList
Expand All @@ -21,12 +25,26 @@ import org.sopt.and.presentation.home.component.Top20List

@Composable
fun HomeScreen(
homeViewModel: HomeViewModel = viewModel()
viewModel: HomeViewModel = hiltViewModel()
) {
val state by viewModel.state.collectAsState()
val context = LocalContext.current
val uiState by homeViewModel.uiState.collectAsState()

// Effect handling
LaunchedEffect(Unit) {
viewModel.effect.collect { effect ->
when (effect) {
is HomeEffect.ShowError -> {
Toast.makeText(context, effect.message, Toast.LENGTH_SHORT).show()
}
HomeEffect.NavigateToDetail -> {
// Handle navigation
}
}
}
}

// Back handler
BackHandler {
(context as? Activity)?.finish()
}
Expand All @@ -38,28 +56,31 @@ fun HomeScreen(
) {
HomeTopBar()

LazyColumn(
modifier = Modifier.fillMaxSize()
) {
item {
BannerView(uiState.bannerImages)
}
if (state.isLoading) {
CircularProgressIndicator(
modifier = Modifier
.fillMaxSize()
.wrapContentSize(),
color = Color.White
)
} else {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
item {
BannerView(state.bannerImages)
}

item {
SectionTitle("믿고 보는 웨이브 에디터 추천작")
EditorPicksList(uiState.editorPicks)
}
item {
SectionTitle("믿고 보는 웨이브 에디터 추천작")
EditorPicksList(state.editorPicks)
}

item {
SectionTitle("오늘의 TOP 20")
Top20List(uiState.top20Items)
item {
SectionTitle("오늘의 TOP 20")
Top20List(state.top20Items)
}
}
}
}
}
@Preview
@Composable
private fun HomeScreenPreview() {
HomeScreen()

}
8 changes: 8 additions & 0 deletions app/src/main/java/org/sopt/and/presentation/home/HomeState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.sopt.and.presentation.home

data class HomeState(
val bannerImages: List<Int> = emptyList(),
val editorPicks: List<String> = emptyList(),
val top20Items: List<String> = emptyList(),
val isLoading: Boolean = false
)
68 changes: 42 additions & 26 deletions app/src/main/java/org/sopt/and/presentation/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,44 +1,60 @@
package org.sopt.and.presentation.home

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import org.sopt.and.R
import javax.inject.Inject

data class HomeUiState(
val bannerImages: List<Int> = listOf(),
val editorPicks: List<String> = listOf(),
val top20Items: List<String> = listOf()
)
@HiltViewModel
class HomeViewModel @Inject constructor() : ViewModel() {
private val _state = MutableStateFlow(HomeState())
val state = _state.asStateFlow()

class HomeViewModel : ViewModel() {
private val _uiState = MutableStateFlow(HomeUiState())
val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()
private val _effect = Channel<HomeEffect>()
val effect = _effect.receiveAsFlow()

init {
loadBannerImages()
loadEditorPicks()
loadTop20Items()
processIntent(HomeIntent.LoadInitialData)
}

private fun loadBannerImages() {
val images = listOf(
R.drawable.banner_image,
R.drawable.banner_image,
R.drawable.banner_image,
R.drawable.banner_image
)
_uiState.value = _uiState.value.copy(bannerImages = images)
fun processIntent(intent: HomeIntent) {
when (intent) {
HomeIntent.LoadInitialData -> loadInitialData()
HomeIntent.RefreshContent -> refreshContent()
}
}

private fun loadEditorPicks() {
val picks = List(5) { "추천작 $it" }
_uiState.value = _uiState.value.copy(editorPicks = picks)
private fun loadInitialData() {
viewModelScope.launch {
_state.update { it.copy(isLoading = true) }

val images = listOf(
R.drawable.banner_image,
R.drawable.banner_image,
R.drawable.banner_image,
R.drawable.banner_image
)
val picks = List(5) { "추천작 $it" }
val items = List(20) { "Top $it" }

_state.update { it.copy(
bannerImages = images,
editorPicks = picks,
top20Items = items,
isLoading = false
) }
}
}

private fun loadTop20Items() {
val items = List(20) { "Top $it" }
_uiState.value = _uiState.value.copy(top20Items = items)
private fun refreshContent() {
loadInitialData()
}
}
}

0 comments on commit 0724052

Please sign in to comment.