最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

kotlin - How to include an error case in the UIState? - Stack Overflow

programmeradmin3浏览0评论

I'm trying to catch any error cases in the ViewModel and update the UIState, but it's not working.

This is the sealed interface to handle the different responses:

sealed interface UniversalisUiState {
    data object Loading : UniversalisUiState

    data class UniversalisData(
        val selectedTopicId: String,
        val topics: UniversalisResource,
    ) : UniversalisUiState

    data object Empty : UniversalisUiState

    data class UniversalisError(
        val message: String,
    ) : UniversalisUiState

}

In the ViewModel the relevant code is:

val uiState: StateFlow<UniversalisUiState> = combine(
    selectedTopicId,
    getUniversalisUseCase.invoke(
        date = selectedDate.value,
        title = route.initialTopicId!!,
        selectedTopicId = LiturgyHelper.liturgyByName(route.initialTopicId!!)
            .toString()
    ).catch {
        //NOT WORKING *******
        //emit(UniversalisUiState.UniversalisError(it.message))
        Timber.d("aaa", it.message)
    },
    UniversalisUiState::UniversalisData,
).stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = Loading,
)

And in the UseCase:

class GetUniversalisUseCase @Inject constructor(
    private val universalisRepository: UniversalisRepository,
    private val userDataRepository: UserDataRepository,
) {

    operator fun invoke(
        date: Int,
        selectedTopicId: String,
        title: String
    ): Flow<UniversalisResource>
    {
        return combine(
            userDataRepository.userData,
            universalisRepository.getUniversalisByDate(
                UniversalisResourceQuery(
                    filterDate = date,
                    selectedTopic = selectedTopicId.toInt()
                )
            ),
        ) { userData, universalis ->
            if (universalis.todayDate == 0 && selectedTopicId != "30") {
                universalisRepository.insertFromRemote(
                    UniversalisResourceQuery(
                        date,
                        selectedTopicId.toInt()
                    )
                )
            }
            UniversalisResource(
                date = universalis.todayDate, 
                title = title,
                name = "",
                id = selectedTopicId.toInt(),
                data = universalis,
                dynamic = userData
            )
        }
    }
}

How I can do this: emit(UniversalisUiState.UniversalisError(it.message)) when catching errors? I can see de error of Timber, but I can't emit UniversalisError.

I'm trying to catch any error cases in the ViewModel and update the UIState, but it's not working.

This is the sealed interface to handle the different responses:

sealed interface UniversalisUiState {
    data object Loading : UniversalisUiState

    data class UniversalisData(
        val selectedTopicId: String,
        val topics: UniversalisResource,
    ) : UniversalisUiState

    data object Empty : UniversalisUiState

    data class UniversalisError(
        val message: String,
    ) : UniversalisUiState

}

In the ViewModel the relevant code is:

val uiState: StateFlow<UniversalisUiState> = combine(
    selectedTopicId,
    getUniversalisUseCase.invoke(
        date = selectedDate.value,
        title = route.initialTopicId!!,
        selectedTopicId = LiturgyHelper.liturgyByName(route.initialTopicId!!)
            .toString()
    ).catch {
        //NOT WORKING *******
        //emit(UniversalisUiState.UniversalisError(it.message))
        Timber.d("aaa", it.message)
    },
    UniversalisUiState::UniversalisData,
).stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = Loading,
)

And in the UseCase:

class GetUniversalisUseCase @Inject constructor(
    private val universalisRepository: UniversalisRepository,
    private val userDataRepository: UserDataRepository,
) {

    operator fun invoke(
        date: Int,
        selectedTopicId: String,
        title: String
    ): Flow<UniversalisResource>
    {
        return combine(
            userDataRepository.userData,
            universalisRepository.getUniversalisByDate(
                UniversalisResourceQuery(
                    filterDate = date,
                    selectedTopic = selectedTopicId.toInt()
                )
            ),
        ) { userData, universalis ->
            if (universalis.todayDate == 0 && selectedTopicId != "30") {
                universalisRepository.insertFromRemote(
                    UniversalisResourceQuery(
                        date,
                        selectedTopicId.toInt()
                    )
                )
            }
            UniversalisResource(
                date = universalis.todayDate, 
                title = title,
                name = "",
                id = selectedTopicId.toInt(),
                data = universalis,
                dynamic = userData
            )
        }
    }
}

How I can do this: emit(UniversalisUiState.UniversalisError(it.message)) when catching errors? I can see de error of Timber, but I can't emit UniversalisError.

Share Improve this question asked Feb 16 at 20:58 A. CedanoA. Cedano 96515 silver badges48 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

Since you want to emit a UniversalisUiState, you need to move the catch after the combine, when the flow is already of that type:

val uiState: StateFlow<UniversalisUiState> = combine(
    selectedTopicId,
    getUniversalisUseCase.invoke(
        date = selectedDate.value,
        title = route.initialTopicId!!,
        selectedTopicId = LiturgyHelper.liturgyByName(route.initialTopicId!!)
            .toString()
    ),
    UniversalisUiState::UniversalisData,
).catch<UniversalisUiState> {
    emit(UniversalisUiState.UniversalisError(it.message))
    Timber.d("aaa", it.message)
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = UniversalisUiState.Loading,
)

You might need to explicitly specify the interface UniversalisUiState as the generic type of catch, so Kotlin can correctly infer the type of the resulting flow.

发布评论

评论列表(0)

  1. 暂无评论