Thread
#compose
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    I want to add a Repeat button. Is it possible to restart flow like this? It seems to work, but Composable is not updated.
    val user by viewModel.loadingUser.collectAsState(initial = null)
    when {
        user.isSucceeded -> navController.navigate(NavScreen.Home.route)
        user.isError -> ErrorConnect { viewModel.repeat() }
        else -> Splash()
    }
    k

    knthmn

    1 year ago
    Is the
    when
    block in a composable? Also what is
    ErrorConnect
    ? Can you show more of your code.
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    @Composable
    loadingUser
    It works, but it seems to me that this is not the right way.
    Paul Woitaschek

    Paul Woitaschek

    1 year ago
    Why would you annotate a launching function as worker thread?
    k

    knthmn

    1 year ago
    There are multiple things 1. Your
    repeat()
    does not restart the
    .collectAsState()
    , instead it just starts collecting the flow independently. Is there a way you can get a flow of the latest
    user
    value from your
    ServiceUser
    ? 2. Code with side effects (such as
    NavController.navigate()
    ) should not be in composable function (see [1]). In your case you can simply switch between what is being displayed by the value of user
    val user by viewModel.loadingUser.collectAsState(null)
    when {
        user.isSuceeded -> TabsHome(...)
        user.isError -> Error()
        null -> Splash()
    }
    Although I don't see the case here, if you really need to have the different screens as destinations , use
    LaunchedEffect()
    val user by viewModel.loadingUser.collectAsState(null)
    LaunchedEffect(user) {
      ... navigate depending on the value of user ...
    }
    [1] https://developer.android.com/jetpack/compose/side-effects
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    1. This looks like right. It works.
    Paul Woitaschek

    Paul Woitaschek

    1 year ago
    Hmm. Without a buffer capacity, wouldn't that tryEmit only work when there is a collector?
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    Is emit better? I'm probably missing something. I did by analogy with LiveData.
    k

    knthmn

    1 year ago
    Since
    RepositoryUser.loadingUser()
    finishes, I would probably do this
    private val _loadingUser: MutableStateFlow<ResponseResult<ModelUser>> = MutableStateFlow(null)
    val loadingUser = _loadingUser.asStateFlow()
    
    init {
        reload()
    }
    
    fun reload() {
        repository.loadingUser()
            .onEach { loadingUser.value = it }
            .launchIn(viewModelScope)
    }
    Ultimately, if
    ServiceUser.getUser()
    cannot be made reactive, I wouldn't bother to wrap it in a flow as you did in
    loadingUser()
    . If I see a
    Flow
    , I assume it to always provides me with the latest value
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    I don't think MutableStateFlow needs to be made public
    k

    knthmn

    1 year ago
    just fixed it
    Vitaliy Zarubin

    Vitaliy Zarubin

    1 year ago
    @knthmn it's working. THX
    @Paul Woitaschek
    Why would you annotate a launching function as worker thread?
    https://developer.android.com/studio/write/annotations#thread-annotations
    Paul Woitaschek

    Paul Woitaschek

    1 year ago
    That makes no sense to me
    You want to annotate functions that block as WorkerThread
    Well actually in coroutines world I would just make blocking functions suspending and wrap it in a withContext(Io)