-
Notifications
You must be signed in to change notification settings - Fork 1
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
[refact/all]: App 추가화면 로직 수정 #158
Conversation
private fun collectState() { | ||
viewModel.state.flowWithLifecycle(lifecycle) | ||
.onEach { binding.btAppSelection.isEnabled = it.appSelectionList.isNotEmpty() } | ||
.launchIn(lifecycleScope) |
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.
UDA 구조 -> 즉 단방향 데이터 통신을 통해 현재 View의 상태를 최신화 할 수 있도록 ViewModel에서 관리하는 State를 참조하도록 하는 코드입니다.
안드로이드에서는 MVI패턴이라고 불려요
}.launchIn(lifecycleScope) | ||
} | ||
btAppSelection.setOnClickListener { handleNextClicked() } | ||
ivBack.setOnClickListener { finish() } |
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.
넹 정답~!!
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.
굳~!!
private val _effect = MutableSharedFlow<AppAddEffect>() | ||
val effect = _effect.asSharedFlow() |
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.
이 effect는 어디서 사용되는 건가요??
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.
해당 effect는 ViewModel -> View로 단방향 이벤트를 쏘기 위해서 사용됩니다.
단발성으로 이루어져야하는 동작에 쓰이며 Event의 경우에는 state보다 더욱 귀중한 자원으로 다뤄야합니다.(이벤트는 한번 발신 후 수신하지 못하면 유실되기 때문)
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.
SharedFlow에 reply를 걸어놓아서 백그라운드 상황의 이벤트에도 대응을 하고싶네요
appSelectionList.filter { | ||
val packageName = it.packageName | ||
val appName = context?.getAppNameFromPackageName(packageName).orEmpty() | ||
!packageName.startsWith(HMH_PACKAGE_NAME) && appName.contains(filter) |
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.
여기서 filter는 무슨 역할을 하는 건가요??
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.
아 새로 추가된 거로 나와서 새로운 기능인줄 알았습니다 허헣
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.
훨씬 깔끔해지고 통일된 것 같습니다. 잘 배워갑니다. 수고하셨습니다~~
val goalTime = goalHour + goalMin | ||
val appSelectionList = installApps.map { AppSelectionModel(it, selectedApps.contains(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.
이거 시간 복잡도가 조금 꺼림칙합니다 더 좋은방법 있다면 추천?
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.
map으로 한번 반복시키고 내부에서 contains로 반복시키면 O^2가 됩니당
private val _effect = MutableSharedFlow<AppAddEffect>() | ||
val effect = _effect.asSharedFlow() |
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.
SharedFlow에 reply를 걸어놓아서 백그라운드 상황의 이벤트에도 대응을 하고싶네요
private fun updateState(transform: AppAddState.() -> AppAddState) { | ||
val currentState = state.value | ||
val newState = currentState.transform() | ||
_state.value = newState | ||
} | ||
|
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.
상태 업데이트는 ViewModel에서만!
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.
구웃
setListeners(appSelectionModel) | ||
} | ||
|
||
private fun initAppSelectionListener(packageName: String) { | ||
binding.root.setOnClickListener { | ||
if (adapterPosition != RecyclerView.NO_POSITION) { | ||
if (binding.cbApp.isChecked) { | ||
binding.cbApp.isChecked = false | ||
onAppCheckboxUnClicked(packageName) | ||
checkBoxStatus.put(adapterPosition, false) | ||
private fun setListeners(appSelectionModel: AppSelectionModel) { |
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.
check된 값에 따라서 클릭리스너가 보여지는 걸 업데이트 하는 함수니까...
updateCheckedApp아니면..
updateCheckedAppListner 등등 .. 이런 식..?
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.
좋은 것 같아요
viewModel.setGoalHour((newTime * 60 * 60 * 1000).toLong()) | ||
} | ||
binding.npUseTimeGoalMinute.setOnValueChangedListener { _, _, newTime -> | ||
activityViewModel.updateState { | ||
copy(goalMin = (newTime * 60 * 1000).toLong()) | ||
} | ||
viewModel.setGoalMin((newTime * 60 * 1000).toLong()) |
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.
구웃 좋은 리팩토링 코드 잘 보고 갑니둥
val goalTime = goalHour + goalMin | ||
val appSelectionList = installApps.map { AppSelectionModel(it, selectedApps.contains(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.
어떤 부분에서 시간 복잡도 걱정이 된다는 건지 자세하게 알 수 있을까용?
|
||
data class AppAddState( | ||
val selectedApp: List<String> = listOf(), | ||
val installApps: List<String> = emptyList(), |
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.
별 거는 아닌데
이 변수도 installedApp으로 하면 어떨까유
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.
아 그리고 전부터 궁금했는데 viewModel에서 우리가 상태 업데이트할 때
state data class나 event object들을 따로 파일로 만들지 않고 viewModel에서 같이 생성하는 이유가
굳이 파일을 만들 필요 없음 + viewModel 파일의 가독성
뿐인것 맞을까용??
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.
넵넵 맞습니다~!!
이름 아주 좋네요
private fun updateState(transform: AppAddState.() -> AppAddState) { | ||
val currentState = state.value | ||
val newState = currentState.transform() | ||
_state.value = newState | ||
} | ||
|
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.
구웃
fun setGoalHour(goalHour: Long) { | ||
updateState { | ||
copy(goalHour = goalHour) | ||
} | ||
} | ||
|
||
fun setGoalMin(goalMin: Long) { | ||
updateState { | ||
copy(goalMin = goalMin) | ||
} | ||
} |
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.
그 리스너가 분리되어있습니다 입력되는 뷰가 달라서요!
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.
아하! 넹~~
setListeners(appSelectionModel) | ||
} | ||
|
||
private fun initAppSelectionListener(packageName: String) { | ||
binding.root.setOnClickListener { | ||
if (adapterPosition != RecyclerView.NO_POSITION) { | ||
if (binding.cbApp.isChecked) { | ||
binding.cbApp.isChecked = false | ||
onAppCheckboxUnClicked(packageName) | ||
checkBoxStatus.put(adapterPosition, false) | ||
private fun setListeners(appSelectionModel: AppSelectionModel) { |
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.
check된 값에 따라서 클릭리스너가 보여지는 걸 업데이트 하는 함수니까...
updateCheckedApp아니면..
updateCheckedAppListner 등등 .. 이런 식..?
private val binding by viewBinding(FrargmentAppSelectionBinding::bind) | ||
private val viewModel by viewModels<AppSelectionViewModel>() | ||
private val activityViewModel by activityViewModels<AppAddViewModel>() | ||
private val viewModel by activityViewModels<AppAddViewModel>() |
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.
AppSelectionViewModel의 프래그먼트 뷰모델 코드를 모두 액티비티의 AppAddViewModel로 옮긴 것 같은데 맞을까요? 프래그먼트 뷰모델에서 하는 일이 없는 것 같은데 그러면 AppSelectionViewModel 파일 지우는 거 어떨까욤
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.
AppSelectionViewModel 요거 지워야할 것 같네요 굳!!
간단한 리팩터링인데 꽤나 고민해보고 고쳐보았습니다.
두 분 다 보시고 어떤 식으로 우리가 좋은 코드를 만들어나가야할지 고민해보면 좋을 것 같아요~!!
보시고 이해 안가는 부분이 있거나 오류가 있는지 알려주세욥