Closed tgyuuAn closed 2 weeks ago
저장소 화면에서 채팅 기록을 들어갔다가 채팅을 하나 치고 나온 뒤, 저장소 화면으로 돌아오면 새로운 데이터로 갱신되어야 하는데,
backstack()
으로 돌아왔기 때문에 새롭게 데이터를 호출하는 로직을 넣기 힘들었음.
// StorageScreen
@Composable
internal fun StorageRoute(
navigateToChatting: (String) -> Unit,
viewModel: StorageViewModel = hiltViewModel(),
) {
val selectedYear by viewModel.selectedYear.collectAsStateWithLifecycle()
val chattingRooms by viewModel.chattingLogs.collectAsStateWithLifecycle()
val yearPickerState = rememberFWheelPickerState()
val (showChatLogDeleteDialog, setChatLogDeleteDialog) = remember { mutableStateOf(false) }
val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(true) {
viewModel.eventFlow.collectLatest { event ->
when (event) {
is StorageViewModel.StorageEvent.DeleteSuccess -> setChatLogDeleteDialog(false)
is StorageViewModel.StorageEvent.EventFailed ->
snackbarHostState.showSnackbar(event.message)
}
}
}
StorageScreen(
snackbarHostState = snackbarHostState,
selectedYear = selectedYear,
chattingRooms = chattingRooms,
yearPickerState = yearPickerState,
showChatLogDeleteDialog = showChatLogDeleteDialog,
setChatLogDeleteDialog = setChatLogDeleteDialog,
deleteChattingRoom = viewModel::deleteChattingRoom,
navigateToChatting = navigateToChatting,
)
}
// StorageViewModel
Inject constructor(
private val getAllChattingLogUseCase: GetAllChattingLogUseCase,
private val deleteChattingRoomUseCase: DeleteChattingRoomUseCase,
) : ViewModel() {
private val _eventFlow = MutableSharedFlow<StorageEvent>()
val eventFlow = _eventFlow.asSharedFlow()
private val _selectedYear = MutableStateFlow("2024")
val selectedYear = _selectedYear.asStateFlow()
private val _chattingLogs = MutableStateFlow<List<ChattingRoom>>(listOf())
val chattingLogs = _chattingLogs.asStateFlow()
init {
getAllChattingLogs()
}
fun event(event: StorageEvent) = viewModelScope.launch { _eventFlow.emit(event) }
private fun getAllChattingLogs() = viewModelScope.launch {
getAllChattingLogUseCase()
.onSuccess { _chattingLogs.value = it }
.onFailure { event(StorageEvent.EventFailed(it.toString())) }
}
즉, popBackStack()
으로 돌아오더라도 ViewModel init 블럭에 있는 getAllChattingLogs()
를 호출해야 했음.
해결책 매우 간단했다.
ViewModel의 init 에서 호출하던 로직을 StorageRouet의 LaunchedEffect()에서 호출하도록 변경하면 되었음. 크크
@Composable
internal fun StorageRoute(
navigateToChatting: (String) -> Unit,
viewModel: StorageViewModel = hiltViewModel(),
) {
val selectedYear by viewModel.selectedYear.collectAsStateWithLifecycle()
val chattingRooms by viewModel.chattingLogs.collectAsStateWithLifecycle()
val yearPickerState = rememberFWheelPickerState()
val (showChatLogDeleteDialog, setChatLogDeleteDialog) = remember { mutableStateOf(false) }
val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(true) {
viewModel.getAllChattingLogs()
viewModel.eventFlow.collectLatest { event ->
when (event) {
is StorageViewModel.StorageEvent.DeleteSuccess -> setChatLogDeleteDialog(false)
is StorageViewModel.StorageEvent.EventFailed ->
snackbarHostState.showSnackbar(event.message)
}
}
}
StorageScreen(
snackbarHostState = snackbarHostState,
selectedYear = selectedYear,
chattingRooms = chattingRooms,
yearPickerState = yearPickerState,
showChatLogDeleteDialog = showChatLogDeleteDialog,
setChatLogDeleteDialog = setChatLogDeleteDialog,
deleteChattingRoom = viewModel::deleteChattingRoom,
navigateToChatting = navigateToChatting,
)
}
속하고있는 navigationGraph의 생명주기를 따라간다.
이 때, hiltViewModel()
말고도 아래와 같이 viewModel()
로도 뷰모델을 생성할 수 있는데,
@Composable
MainScreen(
viewModel: MainViewModel = viewModel()
)
이렇게 될 경우 해당 MainScreen
이 호출될 때마다 ViewModel 인스턴스가 재생성된다.
반면, hiltViewModel()
로 생성된 viewModel은 생명주기가 NavGraph와 같게 됌.
이제 원래는 아래처럼 왼쪽 -> 오른쪽으로 열리는게 default인데,
이제 우리가 원하는 것은 카톡방 서랍처럼 아래 그림이걸랑요
이 때는, 아래 처럼 오른쪽에서 왼쪽으로 읽히듯이 제공하는 layoutDirection을 강제로 Rtl로 바꿔서 우회해서 구현가능....!
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
Column(
modifier = Modifier
.background(BaekyoungTheme.colors.white)
.width((localConfiguration.screenWidthDp.dp * 3) / 4),
) {
Text(
뒤에 ripple 나오는 거 너무 구려요 없애주세요.
clickable
함수는 두 가지 파라미터로 오버로딩이 되어있는데,
이 때 까지 주로 위 함수로 사용했지만,
클릭 시 ripple 효과를 제거 혹은 다른 효과로 변경 하고 싶을 경우 밑의 함수를 사용해야 한다.
아래와 같이 indiciation
에 null을 넣어주면 되는데,
이 때 아래 함수를 사용하기 위해서는 interactionSource
가 필수적으로 들어가야하는 파라미터이기 때문에 아래처럼 해주면 끝!!!
modifier = Modifier.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
) {
// Todo
},
사랑합니ㅏㄷ...
작업 사항
자... 일단 태스크가 너무 크기 때문에... 쪼개보자..
Todo
기타사항
진짜 많네