admin管理员组文章数量:1129461
I am implementing a LivenessScreen in Jetpack Compose with the following code:
LivenessScreen(
viewModel = livenessViewModel,
onErrorScreen = onErrorScreen,
onLivenessComplete = onLivenessComplete
)
Problem: When I pass onErrorScreen and onLivenessComplete as lambda functions to the LivenessScreen, the UiState.Failure case is triggered multiple times under the following conditions:
- When the API fails, the failure case is triggered three times.
- When I press the back button from the system, the failure case is triggered again.
However, when I remove onErrorScreen and onLivenessComplete from the LivenessScreen parameters, the UiState.Failure is triggered only once when the API fails and is not triggered again when pressing the back button.
Observations:
- From the UseCase, the failure state is emitted only once according to the logs.
- The repeated triggers happen only when the lambdas are passed to the LivenessScreen.
Questions:
- What could be causing the UiState.Failure case to be triggered multiple times?
- How can I prevent the repeated triggering of the failure state when using lambdas in Jetpack Compose?
- Are there any best practices to handle lambdas and state management to avoid such issues?
Any help or guidance would be greatly appreciated!
MainActivity.kt
setContent {
val navController = rememberNavController()
NavGraph(navController)
}
NavGraph.kt
@Composable
fun NavGraph(navController: NavHostController) {
NavHost(
navController = navController, startDestination = NavRoute.LiveNess.path
) {
addLivenessScreen(navController, this)
addLiveNessSuccessScreen(navController, this)
}
}
fun addLivenessScreen(navController: NavHostController, navGraphBuilder: NavGraphBuilder) {
navGraphBuilderposable(route = NavRoute.LiveNess.path) {
LivenessRoute(
onLivenessComplete = {
navController.navigate(NavRoute.LiveNessSuccess.path)
},
onErrorScreen = {
navController.navigate(NavRoute.GenericErrorScreen.path)
},
)
}
}
fun addLiveNessSuccessScreen(
navController: NavHostController,
navGraphBuilder: NavGraphBuilder,
config: SDKConfiguration
) {
navGraphBuilderposable(route = NavRoute.LiveNessSuccess.path) {
LivenessSuccessScreen(
)
}
}
LivenessRoute.kt
@Composable
fun LivenessRoute(
onLivenessComplete: () -> Unit,
onErrorScreen: () -> Unit
) {
val livenessViewModel: LivenessViewModel = koinViewModel()
LivenessScreen(
viewModel = livenessViewModel,
onErrorScreen = onErrorScreen,
onLivenessComplete = onLivenessComplete
)
}
LivenessScreen.kt
@Composable
fun LivenessScreen(
modifier: Modifier = Modifier,
onLivenessComplete: () -> Unit,
onErrorScreen: () -> Unit,
viewModel: LivenessViewModel
) {
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
V2Theme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding),// Padding for better spacing
contentAlignment = Alignment.Center // Center content within the Box
) {
when (val state = uiState.value) {
is UiState.Loading -> {
Column(
horizontalAlignment = Alignment.CenterHorizontally, // Center items horizontally
verticalArrangement = Arrangement.Center // Center items vertically
) {
CircularProgressIndicator()
Spacer(modifier = Modifier.height(16.dp))
Text("Loading...")
}
}
is UiState.Success -> {
state.value?.sessionId?.let {
Column(
horizontalAlignment = Alignment.CenterHorizontally, // Center items horizontally
verticalArrangement = Arrangement.Center // Center items vertically
) {
CircularProgressIndicator()
Spacer(modifier = Modifier.height(16.dp))
Text("Loading... $it")
}
}
}
is UiState.Failure -> {
Log.d("FaceLivenessDetector", state.exception.toString())
}
}
}
}
}
}
LivenessViewModel.kt
class LivenessViewModel(private val fetchSessionDataUseCase: FetchSessionDataUseCase) :
ViewModel() {
private val _uiState = MutableStateFlow<UiState<LivenessModel>>(UiState.Loading)
val uiState: StateFlow<UiState<LivenessModel>> get() = _uiState
init {
fetchSessionData()
}
private fun fetchSessionData() {
val request = LivenessRequest(
kmsKeyId = null, // Optional
auditImagesLimit = 3, // Optional
clientRequestToken = generateRandomString(16) // Required
)
viewModelScope.launch {
fetchSessionDataUseCase.invoke(request).collectLatest { apiResult ->
when (apiResult) {
is ApiResult.Success -> {
_uiState.value = UiState.Success(apiResult.value)
}
is ApiResult.Failure -> {
_uiState.value = UiState.Failure(
apiResult.errorType ?: ApiException.UnknownError()
)
}
is ApiResult.Loading<*> -> {
_uiState.value = UiState.Loading // Emit loading state
}
}
}
}
}
}
FetchSessionDataUseCase.kt
class FetchSessionDataUseCase(private val repository: LivenessRepository) {
operator fun invoke(request: LivenessRequest): Flow<ApiResult<LivenessModel?>> {
return flow {
try {
emit(Loading<LivenessModel>())
when (val result = repository.getSessionData(request)) {
is Failure -> {
emit(Failure(ApiException.UnknownError()))
}
is Success -> {
emit(result.mapSuccess {
Success(value)
})
}
else -> {
emit(Failure(ApiException.UnknownError()))
}
}
} catch (e: HttpException) {
emit(
Failure(
ApiException.NetworkError(
e.localizedMessage ?: "An unexpected error occurred."
)
)
)
} catch (e: IOException) {
emit(Failure(ApiException.NetworkError("Couldn't reach server. Check your internet connection.")))
}
}.catch { e ->
emit(Failure(ApiException.UnknownError("An error occurred: ${e.localizedMessage ?: "Unknown error"}")))
}
}
}
LivenessRepository.kt
interface LivenessRepository {
suspend fun getSessionData(request: LivenessRequest): ApiResult<LivenessModel?>
}
LivenessRepositoryImpl.kt
class LivenessRepositoryImpl(
private val dataSource: LivenessRemoteDataSourceImpl
) : LivenessRepository {
override suspend fun getSessionData(request: LivenessRequest): ApiResult<LivenessModel?> {
val apiResult = performRequest<LivenessResponse, LivenessModel>(
request = {
dataSource.getSessionData(
request
)
},
transform = { apiResponse ->
apiResponse.toDomainModel()
},
)
return apiResult
}
}
本文标签: androidHow to Prevent Repeated UiStateFailure CallsStack Overflow
版权声明:本文标题:android - How to Prevent Repeated UiState.Failure Calls? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736745688a1950761.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论