-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: 모험 기록 상세 페이지 뷰 구현 #494
The head ref may contain hidden characters: "feat/#489_\uBAA8\uD5D8_\uAE30\uB85D_\uC0C1\uC138_\uD398\uC774\uC9C0_\uBDF0_\uAD6C\uD604"
Conversation
…23-naaga into feat/#489_모험_기록_상세_페이지_뷰_구현
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
크롱!🦖 고생많았어요!
잠못자고 한 이유가 있었네요ㅋㅋㅋ아니 uiState에 Flow까지 👍
저도 크롱 리뷰하면서 플로우 공부를 같이 좀 했습니다ㅋㅋㅋ
특별히 큰 수정 요구사항은 없어보여 몇가지 질문 및 코멘트 남겼으니 확인해주시면 됩니다!
writeLetters = getOpenLetterUiModels(writeLetters), | ||
adventureResult = adventureResult, | ||
) | ||
}.collectLatest { _uiState.value = it } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collectLatest
가 어떤 일을 하는 아이인가요? 최종적으로 값이 모여졌을 때 value에 넣어주도록 처리해주는 아이인가요??!?!!? 진짜 모름
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collect를 통해 emit한 값을 수집하여 사용할 수 있습니다.
collectLatest 함수는 새로운 값이 방출될 때마다 현재 진행 중인 작업을 취소하고, 가장 최신의 값을 사용하여 새로운 작업을 시작합니다.
다음의 코드를 실행시켜보면 조금 더 쉽게 와닿을 수도 있을 것 같아요!
fun main() = runBlocking {
val flow = flow {
emit(1)
delay(1000)
emit(2)
delay(1000)
emit(3)
}
flow.collectLatest { value ->
println("Received: $value")
delay(3000)
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호... 예제 코드까지 주시다니.. 👍
해당 코드 실행 시켜봤는데 이해가 좀 가기 시작했어요! flow 관련해서 좀더 공부해보고 싶어지네요ㅎㅎㅎㅎ
runCatching { | ||
letterRepository.fetchLetterLogs(gameId, LogType.READ) | ||
}.onSuccess { | ||
readLettersFlow.emit(it) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호..... init 에서 컴바인을 해주면 여기선 success가 될 때 emit만 해주면 되는군요..?
크롱의 flow 강의 기다립니다🤩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
init
블록에서 readLettersFlow
, writeLettersFlow
, adventureFlow
를 combine
하고
collectLatest
를 통해 가장 최신의 값을 사용하여 AdventureDeetailuiState.Success
를 반환합니다.
emit을 해야 collect가 가능합니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아 ~~~~~~~~~ combine된 애들이 emit을 통해 값이 불러와지고 이 아이들이 다 들어오게 되면 collectLatest를 통해 받아오는거군요
오호 대박 이해완!
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.launch | ||
|
||
fun LifecycleOwner.repeatOnStarted(block: suspend CoroutineScope.() -> Unit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 함수는 어떤 일을 하나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LiveData와는 다르게 Flow는 안드로이드의 라이프사이클을 알지 못합니다. 그래서 onStart()에서 collect를 시작하고, onStop()에서 cancel해줘야 하는데요.
Lifecycle
의 확장함수인 Lifecycle.repeatOnLifecycle
은 파라미터로 넣어주는 State에서만 collect를 합니다. 그리고 State 이외의 상태로 갔을 때 collect을 멈추고 다시 State로 돌아가면 collect을 재진행합니다.
따라서 State에 Lifecycle.State.STARTED
를 넣어주면 onStart() 에서만 collect을 할 수 있도록 지정해줄 수 있고, 이를 편하게 사용하기 위한 확장함수를 만든 것입니다. (안만들면 인덴트가 3개는 가뿐히 넘어가더라구요..?)
여기를 참고하면 도움이 될 수도 있겠습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호.... 크롱 덕분에 Flow에 대해 알아가네요! 신기해요! 많이 배워갑니다!!
} | ||
} | ||
|
||
private fun showReRequestSnackbar() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2]
private fun showReRequestSnackbar() { | |
private fun showRequestSnackbar() { |
오타가 있어요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오타...는 아닙니다..🦖
재요청 == Re(재)Request(요청)
의 느낌으로 작성한건데... showRequestSnackbar
로 변경할까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅋㅋㅋㅋㅋㅋ오타가 아니군요!? 앗차차~~~
showRetrySnackbar
는 어떤가요?ㅋㅋㅋㅋ구리면 바로showReRequestSnackbar
로 유지합시다!ㅋㅋㅋ
크롱 말 듣고 다시 보니 showReRequestSnackbar 네이밍도 메서드가 머선일을 하는지 잘 보이는 것 같고 좋네요👍
fun getDefault(): OpenLetterUiModel { | ||
return OpenLetterUiModel("", "", DEFAULT_MESSAGE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P3]
Default 객체를 반환해주는 함수를 생성해 매번 생성해주기 보단 아예 디폴트 객체를 하나 만들어 놓는 건 어떤가요?
fun getDefault(): OpenLetterUiModel { | |
return OpenLetterUiModel("", "", DEFAULT_MESSAGE) | |
val DEFAULT_OPEN_LETTER = OpenLetterUiModel("", "", DEFAULT_MESSAGE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반영했습니다!
…23-naaga into feat/#489_모험_기록_상세_페이지_뷰_구현 # Conflicts: # android/app/src/main/java/com/now/naaga/data/throwable/DataThrowable.kt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생많았어용~~~~~
리뷰 반영한 부분도 확인했고 나머지 로직들도 이해 완료 했습니다!
더 이상 수정할 부분 없는 것 같아 이만 approve하고 merge 하도록 하겠습니다!
👍🦖
📌 관련 이슈
🛠️ 작업 내용
🎯 리뷰 포인트
ViewPager2
UiState
Flow
Flow를 적용하게 된 이유는 다음과 같습니다.
async()
,await()
메서드를 사용하여 구현할 수도 있지만 Flow에서 이미 제공하는 기능을 사용하는 것이 낫지 않을까 생각했습니다. (부족한 시간에 괜히 한 것 같기도 합니다. ㅋㅋ)⏳ 작업 시간
추정 시간: 1h 30m
실제 시간: 8h
수치상으로 보니 차이가 많이 나네요. 뷰를 그리다가 욕심이 나서 뷰페이저를 추가했고, 쪽지 하나의 뷰도 조금이지만 꾸며봤습니다.
Flow를 처음써봐서 학습과 구현 방식에 대해 많이 고민하는 시간을 가졌네요. 추가로 Throwable을 LiveData가 아닌 방식으로 어떻게 구현할 수 있을까에 대해 고민도 해보았습니다.