https://kotlinlang.org logo
Join SlackCommunities
Powered by
# uniflow
  • e

    Erik

    09/07/2020, 12:34 PM
    Thanks, let me know if you need additional eyes on some things. Let's not stall this release
    👍 1
  • a

    arnaud.giuliani

    09/11/2020, 8:25 AM
    @Erik I will try to push the update for 0.11.3 today ... we check your last review
  • a

    arnaud.giuliani

    09/11/2020, 8:26 AM
    Apart of that, I’m working on an issue where we have a long running action (long networking ...) and we restart the same action. Then we enqueue things, and we wait for all the actions to complete. I’m thinking to propose a way of cancelling the running action, to help restart it
    e
    • 2
    • 8
  • a

    arnaud.giuliani

    09/11/2020, 8:26 AM
    @Marcin Chrapowicz @Daniel Beleza did you had such issues with Curve app guys?
    m
    • 2
    • 2
  • a

    arnaud.giuliani

    09/11/2020, 1:23 PM
    0.11.4
    is online 🎉 - https://github.com/uniflow-kt/uniflow-kt/blob/master/Changelog.md
    😀 1
  • o

    Orfeo Ciano

    09/14/2020, 1:50 PM
    Hello everyone! Hi @arnaud.giuliani, how are you doing?
  • o

    Orfeo Ciano

    09/14/2020, 1:50 PM
    I hope you will remember me 😛
    a
    • 2
    • 4
  • o

    Orfeo Ciano

    09/14/2020, 2:01 PM
    I've noticed an issue with UniFlow. Let's assume you want to have different states in quick sequence. Let's take the Android's lifecycle as an example. It's a weird example, but it shows what's the issue. I would like to update the state of the ViewModel while I go through the Activity's Lifecycle callbacks. Activity
    Copy code
    class Activity: Activity{ 
        onCreate() { viewModel.onCreate() }
        onStart() { viewModel.onStart() }
        onResume() { viewModel.onResume() }
        ...
    }
    This is the viewmodel's implementation
    Copy code
    class MyViewModel: AndroidDataFlow(){
        fun onCreate() = actionOn<UIState.Empty>{ setState { MyState.Created } }
        fun onStart() = actionOn<MyState.Created>{ setState { MyState.Started } }
        fun onResume() = actionOn<MyState.Started>{ setState { MyState.Resumed } }
        ...
    }
    Since the system calls
    onCreate
    ,
    onStart
    ,
    onResume
    too quickly, the internal state goes out of sync, causing a
    BadOrWrongState
    (similar to the concurrency issue mentioned earlier). This is because the library needs to check the state when running the action and not before enqueuing it. I have already prepared a fix for that, but I can't push it right now.
  • o

    Orfeo Ciano

    09/14/2020, 2:28 PM
    Here is the patch, I'll try to raise a PR from my personal computer
    check_state_at_runtime.patch
  • a

    arnaud.giuliani

    09/14/2020, 5:17 PM
    when executing the action, we don’t check the current state effectivly 🤔
  • a

    arnaud.giuliani

    09/14/2020, 5:21 PM
    there is a risk when executing, that finally state is not what we expect
  • o

    Orfeo Ciano

    09/14/2020, 5:41 PM
    What do you think about the proposed solution? Can I also get access to the repo so I can create a PR?
  • a

    arnaud.giuliani

    09/14/2020, 6:31 PM
    you can fork and propose a PR: https://github.com/uniflow-kt/uniflow-kt
  • o

    Orfeo Ciano

    09/15/2020, 9:36 AM
    Here you go: https://github.com/uniflow-kt/uniflow-kt/pull/45
  • a

    arnaud.giuliani

    09/15/2020, 9:37 AM
    thanks 👍
  • a

    arnaud.giuliani

    12/04/2020, 10:19 AM
    Hi all 👋 I just pushed a new engine to allow write several streams of data https://github.com/uniflow-kt/uniflow-kt/pull/56
  • a

    arnaud.giuliani

    12/04/2020, 10:39 AM
    cc @Erik @Marcin Chrapowicz ☝️ 👍
    👍 1
  • e

    Erik

    02/18/2021, 7:39 PM
    Why does
    action {}
    return
    ActionFlow
    instead of
    Unit
    , is there a use case to have that object somewhere outside of the Uniflow internals?
    a
    • 2
    • 9
  • e

    Erik

    03/01/2021, 2:11 PM
    I wonder if the following is a UniFlow bug: https://gist.github.com/erikhuizinga/05a2712bdb0f32c45fa192cd137770e0 UniFlow's internals use
    CoroutineScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) { action() }
    (not literally, but that's what it comes down to). If you create a lot of
    action {}
    actions quickly, or if your system is slow, then these launched coroutines aren't necessarily run in order. Remember: launching is fire-and-forget. You don't know when the coroutine is actually run! So, is my code just an example of bad practice? Or is my code an example of a UniFlow running actions in an unordered fashion, and is that a bug?
    a
    • 2
    • 34
  • a

    arnaud.giuliani

    03/18/2021, 5:09 PM
    Pushing first stable version of Uniflow 🎉 https://github.com/uniflow-kt/uniflow-kt
    ❤️ 3
    🎉 6
  • d

    Davide C

    04/12/2021, 1:52 PM
    Hi! Are there any updates about Multiplatform?
    a
    • 2
    • 2
  • a

    arnaud.giuliani

    04/15/2021, 7:53 AM
    Uniflow in Kotlin London ->

    https://www.youtube.com/watch?v=B1t-nAhCAhs▾

    🎉 4
  • d

    Davide C

    05/13/2021, 7:00 PM
    Hi! Can you please give me a hint on which is the best practice in a scenario with two or more parallel sources updating the UIState? In this example the state is updated by a "polling service" every second and by an "on-click service" which takes 3 seconds to complete, while the on-click action is running the polling actions are queued and the state is not updated. I tried to move the on-click call out of the action, it works but i'm not sure it's the right way...
    e
    • 2
    • 3
  • p

    pitpit

    05/25/2021, 10:30 AM
    where to find example of use datalivepublisher access into fragment ?
    a
    • 2
    • 2
  • m

    miqbaldc

    06/14/2021, 5:37 PM
    Does uniflow-kt currently not support StateFlow? Still comparing tools, currently using the orbit-mvi, but interested with uniflow-kt Guard type also ability to share ViewModel based on this videos here:

    https://youtu.be/m6dyIv1rDdo▾

    a
    • 2
    • 1
  • s

    Stephan Schuster

    08/10/2021, 10:19 PM
    Hi! I'm an "experienced old-school Android developer" who is trying to learn and establish a new tech stack based on Kotlin, Coroutines, Flow, MVI/UDF, Jetpack Compose and related stuff. Currently, I know very little about these things. So please forgive me if I am asking too many stupid questions below. If so, just ignore me... After studying lots of articles, videos, MVI framworks and sample code, I decided to go with either orbit-mvi or uniflow-kt. Both are great frameworks and apply MVI/UDF without much boilerplate. As such, my decision cannot be too wrong. Nevertheless, I would like to (but due to lack of knowledge cannot) fully understand the pros and cons on either side. That's where I need your "objective" help. :-) In general, I feel that uniflow-kt has a simpler, cleaner and more consistent API with better naming. By intention it abstracts away more stuff. I guess for a newbie like me, this makes it easier in the beginning. But will it also pay off in the long run or will I be limited somewhen in the future once I am a bit more experienced with "the new shit"? Are there any limitations at all, e.g. when not exposing Flows? In fact, uniflow-kt relies solely on LiveData for state and events while I basically read everywhere that StateFlow and SharedFlow/Channel is the way to go for MVI. Is this true? Should this bother me? Or is it really just an implementation detail? I cannot tell at the moment. Quite similar, this comment here: https://medium.com/@josip.krnjic/i-dont-like-the-setstate-method-ead7253ced9c. Can really all mentioned downsides be handled with the uniflow-kt features listed here: https://github.com/uniflow-kt/uniflow-kt/blob/master/doc/coroutines.md? Next question as found here: https://medium.com/@tfcporciuncula/whats-the-motivation-to-have-the-io-dispatcher-as-the-default-465a48c109ff. Why was IO chosen as default dispatcher over Main even though it always entails 2 thread switches? What actually happens when my ViewModel was destroyed when returning from IO? Some more thoughts - mainly related to this nice MVI framework comparison (written by orbit-mvi): https://proandroiddev.com/top-android-mvi-libraries-in-2021-de1afe890f27 • Inheritance instead of composition is okay for me. It's surely less flexible but sufficient and a bit simpler in most cases. • The "generics" issue mentioned in the article seems to be misunderstood, do you agree? In fact, I prefer being able to use any UIState and UIEvent in my AndroidDataFlow without the need to specify a single type or even Nothing upfront. This simplifies the API, should provide more flexibility (if not misused) and also makes handling states and events in the view more consistent (both with "when"). • I cannot judge the fact that uniflow-kt runs actions in sequence via actor. Could this really lead to potential unresponsive UIs? Was running actions in parallel considered to be a bad idea? If yes, why? • Last thing: multiplatform. Of course it would be nice. But I don't need it for now and assume things would become more complex then. Is there a rough guess if and when it will be available for uniflow-kt? So many questions, I know... Sorry and thanks for reading until here. I would really appreciate if you could answer or comment on some of them. Anything else I should consider when choosing between orbit-mvi and uniflow-kt?
    a
    • 2
    • 11
  • j

    Justin Ramos

    10/18/2021, 7:39 PM
    Hi All, we’ve been using Uniflow-kt for an android app at a fintech company in Mexico for the last year and it’s been great so far. We’re updating from
    0.11.6
    to
    1.0.10
    and ran into an issue and wanted to reach out to the community to see what you all recommend. Below is how we’ve been testing the default state of our viewmodels and we’ve never had issues.
    Copy code
    class FeatureFlagViewModel(
        private val featureFlagStorage: FeatureFlagStorage
    ) : AndroidDataFlow(defaultState = FeatureFlagScreenState(isButtonVisible = featureFlagStorage.getFeatureFlagState()!!)) {...}
    Copy code
    class FeatureFlagViewModelTest : BaseCovaltoUnitTest() {
        private val mockFeatureFlagStorage: FeatureFlagStorage = mockk(relaxed = true)
        private lateinit var viewModel: FeatureFlagViewModel
        private lateinit var view: TestViewObserver
    
        @Before
        fun setup() {
            coEvery {
                mockFeatureFlagStorage.getFeatureFlagState()
            } returns true
    
            viewModel = FeatureFlagViewModel(mockFeatureFlagStorage)
            view = viewModel.createTestObserver()
        }
    
        @Test
        fun `Should set feature flag states properly by default`() {
            assertThat(view.lastStateOrNull)
                .isEqualTo(
                    FeatureFlagScreenState(isCreateAccountButtonVisible = true)
                )
        }
    When I run the tests after upgrading to the stable version it fails with the error in the photo below. The issue seems to be that the viewmodel is initialized before it can be observed so we never see the default state set. In other tests when we call
    viewModel.doStuff()
    the viewmodel state is properly updated. An easy fix is to create the default state in the init method of the viewModel like this:
    Copy code
    class FeatureFlagViewModel(
        private val featureFlagStorage: FeatureFlagStorage
    ) : AndroidDataFlow() {
    
        init {
            action {
                setState(FeatureFlagScreenState(isCreateAccountButtonVisible = featureFlagStorage.getFeatureFlagState()!!))
            }
        }
    However, this feels a bit cumbersome to do in every viewmodel we have. It would be great to keep instantiating state the way we’re currently doing it. What do you guys recommend we do though?
    e
    a
    • 3
    • 5
  • e

    Erik

    10/29/2021, 9:49 AM
    FYI, I opened an issue about this with an MWE: https://github.com/uniflow-kt/uniflow-kt/issues/86
    🙌 1
  • e

    Erik

    11/09/2021, 3:11 PM
    FYI: https://github.com/uniflow-kt/uniflow-kt/issues/87
    a
    • 2
    • 1
  • a

    arnaud.giuliani

    11/16/2021, 9:41 AM
    I will look at current issues at end of November. Still have lots to do on Koin side 🤷
    👍 1