Dirtfy / PPP

0 stars 0 forks source link

stream의 state 관리할 때 #72

Open WeGlonD opened 1 week ago

WeGlonD commented 1 week ago
    private val accountListFlow = accountBusinessLogic.accountStream()
        .catch { cause ->
            _screenData.update { it.copy(accountListState = UiScreenState(UiState.FAIL, cause.message)) }
        }
        .map { it.map { account -> account.convertToUiAccount(0) } }

    override val screenData: Flow<UiAccountListScreenState>
        = _screenData
        .combine(accountListFlow) { state, accountList ->
            val filteredAccountList = accountList.filter {
                it.number.contains(state.searchClue)
            }

            var newState = state.copy(
                accountList = filteredAccountList,
            )

            if (state.accountList != accountList // 내용이 달라졌을 때
                || state.accountList !== accountList // 내용이 같지만 다른 인스턴스
                || accountList == emptyList<UiAccount>()) // emptyList()는 항상 같은 인스턴스
                newState = newState.copy(
                    accountListState = UiScreenState(state = UiState.COMPLETE)
                )

            newState
        }

기존에는 이렇게 해 왔는데

            if (state.accountList != accountList // 내용이 달라졌을 때
                || state.accountList !== accountList // 내용이 같지만 다른 인스턴스
                || accountList == emptyList<UiAccount>()) // emptyList()는 항상 같은 인스턴스
                newState = newState.copy(
                    accountListState = UiScreenState(state = UiState.COMPLETE)
                )

위 부분에서 backing property가 아닌 새로 만드는 state의 멤버를 변경한다.

그래서 한번 Fail이 되면 backing property의 해당 멤버는 나중에 Complete 상태로 stream을 잘 받아오더라도 Fail인 그대로 유지된다.

이후 screenState 정의에서 combine 으로 합쳐진 다른 flow가 emit하여 해당 블록을 다시 실행할 경우, accountList의 변경사항이 없기 때문에 backing property에 저장된 Fail이 state로 들어갈 가능성이 있어보인다.

그래서 위 if문을 다음과 같이 바꾸는게 좋아보인다.

            if (state.accountList != accountList // 내용이 달라졌을 때
                || state.accountList !== accountList // 내용이 같지만 다른 인스턴스
                || accountList == emptyList<UiAccount>()) // emptyList()는 항상 같은 인스턴스
                _screenData.update { it.copy(
                    accountListState = UiScreenState(state = UiState.COMPLETE)
                ) }

이러면 중복 연산이 될 거 같기도 해서 다른 해결책이 있다면 더 좋을 거 같은데

여러분의 생각이 궁금하군요.

DongGi-create commented 1 week ago

backing property로 하는것은 맞아 보입니다. 아주 좋은 변경인듯 합니다. 중복에 관해서는 좀 찾아봤는데

image 이건 어떤지..

override val screenData: Flow = _screenData.combine(accountListFlow) { state, accountList -> ... }.distinctUntilChanged()

동일한 값을 방출할때는 방출하지 않도록 해준다고 합니다.. 1, 1, 2, 2, 3 -> 1, 2, 3 1, 2, 2, 1, 3 -> 1, 2, 1, 3