#1 ๊ฐ์
๊ธฐ์กด์๋ ๋ฌดํ ์คํฌ๋กค์ ์ํ ์์์ ์คํฌ๋กค ๋ก์ง์ ViewModel๊ณผ View๊ณผ ์๋ถํ๊ณ ์์๋ค. ๋ณธ ๊ฒ์๊ธ์์ ์ด ์คํฌ๋กค ๊ด๋ จํ ๋ก์ง์ View์ ์ผ์ํ๋ค. ViewModel์ ์ด์ LazyColumn์ด ๋ณด์ ํ ์์ดํ
๋ฆฌ์คํธ์ ์ถ๊ฐใ์ ๊ฑฐ๋ง ์ํํ๋ฉด ๋ ๊ฒ์ด๋ค.
#2 ์ฝ๋
#2-1 ViewModel์์์ Scroll ๊ด๋ จ ์ฝ๋ ์ญ์
...
class NutrientViewModel : ViewModel() {
// (1) ํ๋ฉด ํ์์ฉ State
...
// (2) ViewModel์ฉ ๋ด๋ถ ๋ณ์
...
// (3) View์์ ๋ฐ์ ์ฒ๋ฆฌํ ์ด๋ฒคํธ
...
// (4) View๋ก๋ถํฐ ๋ฐ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ
fun onEvent(event: NutrientViewModelEvent) {
when (event) {
is NutrientViewModelEvent.InitializeState -> {
...
}
is NutrientViewModelEvent.LoadMoreItemsAfterLastDate -> {
...
}
is NutrientViewModelEvent.LoadMoreItemsBeforeFirstDate -> {
val firstDate = _nutrientScreenState.value.dailyMeals.first().date
_nutrientScreenState.value.dailyMeals.add(
0,
DailyMeal(
date = firstDate.minusDays(1),
meals = SnapshotStateList()
)
)
/* ์ ๊ฑฐ
viewModelScope.launch {
_nutrientScreenEventFlow.emit(NutrientScreenEvent.RequestScrollToItem(1))
}
*/
}
}
}
}
ViewModel๋ถํฐ ๊น๋ํ๊ฒ ๋ง๋ ๋ค.
#2-2 NutrientScreenEvent.RequestScrollToItem ์ญ์
...
sealed class NutrientScreenEvent {
data class ShowSnackbar(val message: String) : NutrientScreenEvent()
/* ์ ๊ฑฐ
data class RequestScrollToItem(val index: Int) : NutrientScreenEvent()
*/
}
์ด์ ํ์์๋ ์ด๋ฒคํธ์ด๋ฏ๋ก ์ญ์ ํ๋ค.
#2-3 ์คํจํ ์๋: ์๋ก์ด LaunchedEffect() ์์ญ ์์ฑ
...
@Composable
fun NutrientScreen(
...
) {
LaunchedEffect(key1 = true) {
// State ์ด๊ธฐํ
...
// ViewModel๋ก๋ถํฐ ๋ฐ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ
...
}
LaunchedEffect(key1 = viewModel.nutrientScreenState.value.dailyMeals.getOrNull(0)) {
// ์ญ๋ฐฉํฅ ๋ฌดํ ์คํฌ๋กค ๊ตฌํ์ ์ํ ์์์ ์คํฌ๋กค
listState.requestScrollToItem(1, listState.firstVisibleItemScrollOffset)
}
LaunchedEffect(key1 = viewModel.isInitialized.value) {
if(viewModel.isInitialized.value) {
// ๋ฌดํ ์คํฌ๋กค
...
}
}
LazyColumn(
...
) {
...
}
}
[์์ดํ
๋ฆฌ์คํธ ์ถ๊ฐ → Recomposition]์ [์์ดํ
๋ฆฌ์คํธ ์ถ๊ฐ → requestScrollToItem → Recomposition]์ผ๋ก ๋ง๋๋ ๊ฒ์ด ๋ชฉ์ ์ธ๋ฐ, ์ ์ฝ๋์ ๊ฐ์ด ์๋ก์ด LaunchedEffect() ์์ญ์ ์ ์ธํ๋ฉด ์ด ์์๊ฐ ์ ๋๋ก ์ง์ผ์ง์ง ์๋๋ค. LaunchedEffect()๋ ์ฝ๋ฃจํด ์์ญ์ ์์ฑํ๋ ํจ์๊ณ , ๋ฐ๋ผ์ ๋น๋๊ธฐ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ ์ฝ๋๋๋ก ์ฑ์ ์คํ์์ผ๋ณด๋ฉด 0.1์ด์ ๋ฒ๋ฒ
์์ด ๋์ ๋ณด์ธ๋ค.
#2-4 ์ฑ๊ณตํ ์๋: ๊ธฐ์กด ๋ฌดํ ์คํฌ๋กค ๊ด๋ จ LaunchedEffect() ์์
...
@Composable
fun NutrientScreen(
...
) {
LaunchedEffect(key1 = true) {
// State ์ด๊ธฐํ
...
// ViewModel๋ก๋ถํฐ ๋ฐ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ
...
}
LaunchedEffect(key1 = viewModel.isInitialized.value) {
if(viewModel.isInitialized.value) {
// ๋ฌดํ ์คํฌ๋กค
snapshotFlow { listState.layoutInfo.visibleItemsInfo }.collect { visibleItemsInfo ->
...
if(totalMaxIndex <= firstVisibleItemIndex + visibleItemCount) {
...
}
if(firstVisibleItemIndex == 0) {
viewModel.onEvent(NutrientViewModelEvent.LoadMoreItemsBeforeFirstDate)
// ์ญ๋ฐฉํฅ ๋ฌดํ ์คํฌ๋กค ๊ตฌํ์ ์ํ ์์์ ์คํฌ๋กค
listState.requestScrollToItem(1, listState.firstVisibleItemScrollOffset)
}
}
}
}
LazyColumn(
...
) {
...
}
}
์์ดํ
๋ฆฌ์คํธ์ ์์ดํ
์ ์ถ๊ฐํ๋ ์์ฒญ์ธ viewModel.onEvent(NutrientViewModelEvent.LoadMoreItemsBeforeFirstDate) ์ดํ ๋ฐ๋ก requestScrollToItem์ ๋๊ธฐ์ ์ผ๋ก ์ํํ๊ธฐ ๋๋ฌธ์ [์์ดํ
๋ฆฌ์คํธ ์ถ๊ฐ → requestScrollToItem → Recomposition]๋ผ๋ ์์๊ฐ ๋ฐ๋์ ์ง์ผ์ง๋ค. ์ฆ 1ํ๋ ์์กฐ์ฐจ ๋ฒ๋ฒ
์ด๋ ์๊ฐ์ด ์๋ค๋ ์๊ธฐ๋ค.
#2-5 ViewModel์ ์๋ 'delay(100)' ์ ๊ฑฐ
...
class NutrientViewModel : ViewModel() {
// (1) ํ๋ฉด ํ์์ฉ State
...
// (2) ViewModel์ฉ ๋ด๋ถ ๋ณ์
...
// (3) View์์ ๋ฐ์ ์ฒ๋ฆฌํ ์ด๋ฒคํธ
...
// (4) View๋ก๋ถํฐ ๋ฐ์ ์ด๋ฒคํธ ์ฒ๋ฆฌ
fun onEvent(event: NutrientViewModelEvent) {
when (event) {
is NutrientViewModelEvent.InitializeState -> {
...
repeat(20) {
...
}
/* ์ ๊ฑฐ
viewModelScope.launch {
delay(100)
_isInitialized.value = true
}
*/
_isInitialized.value = true // ์ถ๊ฐ
}
is NutrientViewModelEvent.LoadMoreItemsAfterLastDate -> {
...
}
is NutrientViewModelEvent.LoadMoreItemsBeforeFirstDate -> {
...
}
}
}
}
์ด์ ๊ฒ์๊ธ์์ , ์ด๊ธฐ ํ๋ฉด์์ ์ด์ ๋ ์ด ์ฒซ ์์ดํ
์ผ๋ก ๋์ค๋ ๋ฒ๊ทธ๊ฐ ์์๋ค. ์ด ๋ฌธ์ ํด๊ฒฐ์ ์ํด ViewModel์ ์๋ฏธ ์๋ delay(100) ์ฝ๋๋ฅผ ๋ฃ์ด์ฃผ์๋๋ฐ ์ด ๋ถ๋ถ์ ์ ๊ฑฐํ๋ค. ViewModel๊ณผ View์ ๋ช
ํํ ์ญํ ๋ถ๋ฆฌ๋ก ์ด์ ์คํฌ๋กค์ด ๊ผฌ์ผ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
#3 ์์ฝ
ViewModel์ด ์ง์ด์ง ํ์๊ฐ ์๋ ์คํฌ๋กค ๊ด๋ จ ๋ก์ง์ View์ ์ผ์ํ๋ค.
#4 ์์ฑ๋ ์ฑ
#4-1 ์๋ ์์
์ด์ ๊ฒ์๊ธ๊ณผ ๋์ผํ๊ฒ ์๋ํ๋ค. ๋ฌผ๋ก , ๋ด๋ถ์ ์ผ๋ก ๋ ๊ฐ๋ณ๊ณ ์ง๊ด์ ์ผ๋ก ๋ณํ๋ค.
#4-2 ์ด ๊ฒ์๊ธ ์์ ์ Commit
GitHub - Kanmanemone/nutri-capture-new
Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.
github.com
#4-3 ๋ณธ ํ๋ก์ ํธ์ ๊ฐ์ฅ ์ต์ Commit
GitHub - Kanmanemone/nutri-capture-new
Contribute to Kanmanemone/nutri-capture-new development by creating an account on GitHub.
github.com
'๊ฐ๋ฐ ์ผ์ง ๐ป > Swemo' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Nutri Capture - ์ ERD์ Room์ @Entity ์ ์ (2) | 2024.10.23 |
|---|---|
| Nutri Capture - Card ์ปดํฌ๋ํธ (0) | 2024.10.17 |
| Nutri Capture - requestScrollToItem()์ ์ด์ฉํ ๊น๋ํ ์ญ๋ฐฉํฅ ๋ฌดํ ์คํฌ๋กค (1) | 2024.10.16 |
| Nutri Capture - ์ญ๋ฐฉํฅ ๋ฌดํ ์คํฌ๋กค (2) | 2024.10.12 |
| Nutri Capture - ๋ฌดํ ์คํฌ๋กค ๋ก์ง ๋ถ๋ฆฌ (0) | 2024.10.12 |