Почему крашится приложение, когда входит в состояние Error? 2024-11-12 16:16:52.270  4295-4295  AndroidRuntime          today.maxi.mobile.dev                E  FATAL EXCEPTION: main
                                                                                                    Process: today.maxi.mobile.dev, PID: 4295
                                                                                                    BusinessLogicValidException(code=REQUEST_ERROR, message=Ошибка получения информации с сервера.)
                                                                                                    	at ru.maxi.mobile.core.network.utils.RestResponseTransformerKt$makeApiRequest$2.invokeSuspend(RestResponseTransformer.kt:74)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:99)
                                                                                                    	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:113)
                                                                                                    	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:589)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:823)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:720)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:707)
                                                                                                    	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@9cff628, Dispatchers.Main.immediate]
package ru.maxi.mobile.feature.achievements.ui.container

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import by.kirich1409.viewbindingdelegate.viewBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import ru.maxi.mobile.R
import ru.maxi.mobile.base.ui.BaseContainerFragment
import ru.maxi.mobile.core.data.LoadableData
import ru.maxi.mobile.databinding.FragmentAchievementsContainerBinding
import ru.maxi.mobile.feature.achievements.ui.container.model.AchievementsRegistrationState

/**
 * [Fragment] контейнера функционала достижений
 */
@AndroidEntryPoint
class AchievementsContainerFragment : BaseContainerFragment(
    R.layout.fragment_achievements_container,
    routerKey = "ACHIEVEMENTS",
) {

    override val viewBinding by viewBinding(FragmentAchievementsContainerBinding::bind)

    private val viewModel by viewModels<AchievementsContainerViewModel>()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        actionBarManager.setTitle(R.string.achievements_screen_title)
        actionBarManager.showBackButton()

        viewBinding.noConnectionView.setOnActionButtonClickListener(viewModel::refreshData)

        // viewModel.getRegistrationState()
        // Log.d("TESTING", "FRAGMENT ${viewModel.getRegistrationState()}")
        with(viewLifecycleOwner) {
            lifecycleScope.launch {
                repeatOnLifecycle(Lifecycle.State.STARTED) {
                    viewModel.viewState.collect(::onRegistrationStateChange)
                }
            }
        }
    }

    private fun onRegistrationStateChange(state: LoadableData<AchievementsRegistrationState>) {
        when (state) {
            is LoadableData.Error -> with(viewBinding) {
                loaderView.hide()
                noConnectionView.isVisible = true
                Log.d("TESTING", "STATE = ERROR")
            }

            is LoadableData.Loading -> with(viewBinding) {
                loaderView.show()
                noConnectionView.isVisible = false
                Log.d("TESTING", "STATE = LOADING")
            }

            is LoadableData.Success -> {
                val isRegistered = state.value.isRegistered
                Log.d("TESTING", "STATE = SUCCESS | state.value.isRegistered = ${state.value.isRegistered}")
                with(viewBinding) {
                    loaderView.hide()
                    noConnectionView.isVisible = false
                }
                if (isRegistered) {
                    
                }
            }
        }
    }
}
package ru.maxi.mobile.feature.achievements.ui.container

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.onSubscription
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import ru.maxi.mobile.core.data.LoadableData
import ru.maxi.mobile.core.data.emitError
import ru.maxi.mobile.core.data.emitLoading
import ru.maxi.mobile.core.data.emitSuccess
import ru.maxi.mobile.core.data.isLoading
import ru.maxi.mobile.feature.achievements.domain.GetAchievementsRegistrationStateUseCase
import ru.maxi.mobile.feature.achievements.ui.container.model.AchievementsRegistrationState
import ru.maxi.mobile.feature.scratchCards.model.ScratchCardsRegistrationState
import javax.inject.Inject

/**
 * [ViewModel] для контейнера функционала достижений
 */
@HiltViewModel
class AchievementsContainerViewModel @Inject constructor(
    private val getAchievementsRegistrationState: GetAchievementsRegistrationStateUseCase
) : ViewModel() {

    private val _viewState = MutableStateFlow<LoadableData<AchievementsRegistrationState>>(LoadableData.Loading())

    /** Состояние данных экрана */
    val viewState: Flow<LoadableData<AchievementsRegistrationState>> = _viewState.asStateFlow()
        .onSubscription { getRegistrationState() }
        .stateIn(viewModelScope, SharingStarted.Lazily, _viewState.value)

    /**
     * Обновить данные функционала
     */
    fun refreshData() {
        if (_viewState.isLoading) return
        _viewState.emitLoading(saveValue = false)
        viewModelScope.launch {
            getRegistrationState()
        }
    }

    private suspend fun getRegistrationState() {
        viewModelScope.launch {
            try {
                _viewState.emitLoading()
                val getRegistrationStateAsync = async { getAchievementsRegistrationState() }
                Log.d("TESTING", "getAchievementsRegistrationState() ${getAchievementsRegistrationState()}")
                val registrationState = getRegistrationStateAsync.await()
                _viewState.emitSuccess(registrationState)
            } catch (exception: Exception) {
                _viewState.emitError(exception)
            }
        }
    }
}