필자가 앱을 완료하고 리팩토링을 하는 중이었습니다.
override fun getAllBudgetsToFlowWhenBudgetChanged(): Flow<List<Budget>> = flow {
budgetDataSource.getAllBudgetsOrederByDateToFlow().collect { budgets ->
val list = budgets.map { budget ->
val categoryProceduresList =
categoryProceduresDataSource.getAllCategoryProceduresWithBudgetNum(budget.num)
val reduce = categoryProceduresList.sumOf { categoryProcedures ->
categoryProcedures.procedures.orEmpty().sumOf { it.money }
}
budget.resultMoeny = budget.money - reduce
budget
}
emit(list)
}
}
override fun getAllBudgetsToFlowWhenProcedureChanged(): Flow<List<Budget>> = flow {
procedureDataSource.getAllProceduresToFlow().collect {
val list = budgetDataSource.getAllBudgetsOrederByDate().map { budget ->
val categoryProceduresList =
categoryProceduresDataSource.getAllCategoryProceduresWithBudgetNum(budget.num)
val reduce = categoryProceduresList.sumOf { categoryProcedures ->
categoryProcedures.procedures.orEmpty().sumOf { it.money }
}
budget.resultMoeny = budget.money - reduce
budget
}
emit(list)
}
}
해당코드는 가계부 테이블과 과정 테이블을 추가할 때 이런 식으로 flow안에서 collect를 사용하는데 collect에서 emit을 수행 하기때문에 가독성이 안좋았습니다. 이때는 블로그에서 받아와서 대충 이해하고 있었지만 리팩토링을 하며 하나하나 따지며 채크를 하다보니 가독성이 별로 좋지도 않고 매번 collect를 한다는 점이 좋지 않았습니다. 그래서 collectLatest를 사용하니
이런식으로 에러가 생겼습니다. 알아보니 collect 함수를 사용할 때는 Flow의 모든 값을 순차적으로 처리하므로 다른 코루틴에서 동시에 Flow를 변경해도 문제가 발생하지 않지만 collectLatest를 사용할 때는 Flow의 최신 값만을 처리하므로, 다른 코루틴에서 동시에 Flow를 변경하면 문제가 될 수 있다고 합니다. 이때는 channelFlow를 사용해야 합니다. 그러다 flatMapLatest를 찾았습니다.
이런 식으로 최신값만 처리하고 중첩으로 flow를 관리할 수 있는 함수입니다.
override fun getAllBudgetsToFlowWhenBudgetChanged() = budgetDataSource.getAllBudgetsOrederByDateToFlow()
.flatMapLatest { budgets ->
flow {
val list = budgets.map { budget ->
val categoryProceduresList =
categoryProceduresDataSource.getAllCategoryProceduresWithBudgetNum(budget.num)
val reduce = categoryProceduresList.sumOf { categoryProcedures ->
categoryProcedures.procedures.orEmpty().sumOf { it.money }
}
budget.resultMoeny = budget.money - reduce
budget
}
emit(list)
}
}
override fun getAllBudgetsToFlowWhenProcedureChanged() = procedureDataSource.getAllProceduresToFlow()
.flatMapLatest { procedures ->
flow {
val list = budgetDataSource.getAllBudgetsOrederByDate().map { budget ->
val categoryProceduresList =
categoryProceduresDataSource.getAllCategoryProceduresWithBudgetNum(budget.num)
val reduce = categoryProceduresList.sumOf { categoryProcedures ->
categoryProcedures.procedures.orEmpty().sumOf { it.money }
}
budget.resultMoeny = budget.money - reduce
budget
}
emit(list)
}
}
리팩토링한 코드입니다
private suspend fun calculateBudgetResult(budget: Budget): Budget {
val categoryProceduresList = categoryProceduresDataSource.getAllCategoryProceduresWithBudgetNum(budget.num)
val reduce = categoryProceduresList.sumOf { categoryProcedures ->
categoryProcedures.procedures.orEmpty().sumOf { it.money }
}
return budget.copy(resultMoeny = budget.money - reduce)
}
override fun getAllBudgetsToFlowWhenBudgetChanged() = budgetDataSource.getAllBudgetsOrederByDateToFlow()
.flatMapLatest { budgets ->
flow {
val list = budgets.map { budget ->
calculateBudgetResult(budget, categoryProceduresDataSource)
}
emit(list)
}
}
override fun getAllBudgetsToFlowWhenProcedureChanged() = procedureDataSource.getAllProceduresToFlow()
.flatMapLatest { procedures ->
flow {
val list = budgets.map { budget ->
calculateBudgetResult(budget, categoryProceduresDataSource)
}
emit(list)
}
}
중복되는 코드 또한 리팩토링 하여 함수를 새로 만들었습니다.
참고
'안드로이드 > 안드로이드' 카테고리의 다른 글
Planfit 프로젝트하면서 생긴 이슈 및 해결 ,기술 정리 (2) | 2024.09.14 |
---|---|
Planfit onBoarding 페이지 클론 코딩 회고 (1) | 2024.09.13 |
[Android/Kotlin] 액티비티의 종료로 ViewModel이 죽어버렸다! (1) | 2023.10.29 |
[Android/Kotlin] 알림(Notification) - 2, 알림의 속성 (1) | 2023.10.29 |
[Android/UI] BackGroundTint 값 Hex값으로 설정 (0) | 2023.10.16 |