https://kotlinlang.org logo
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
ballast
  • l

    lazt omen

    01/02/2023, 1:34 PM
    Hi. Anyone using ballast in a KMM project. I’m new to iOS development and I wanted to know if ballast was a good fit here, or even if it was a good idea bringing the common code to the MVI framework in the first place.
    c
    • 2
    • 1
  • c

    Casey Brooks

    01/04/2023, 5:42 PM
    Hey everyone, with the recent release of Kotlin 1.8, I am starting prep on a new major version of Ballast to go along with it. With a major release of Ballast comes the opportunity to improve its API, and I’d love to know if there are any particular features of APIs that you would like to see changed. I’ve got my own list of potential changes from discussions here, but please leave a comment here or an issue on the repo if there’s something else you’d like to see improved.
  • r

    Robert Jaros

    01/06/2023, 1:17 PM
    When I've exceeded 20 inputs for the view model, my InputHandler class became too large to manage comfortably. It's not trivial to partition the class into smaller pieces. I've tried to split my view model, but it was a dead end (my state class is not large and is really shared by most of those inputs).
    c
    • 2
    • 3
  • a

    Andromadus Naruto

    01/10/2023, 9:58 PM
    Any code examples on how to handle side effects using ballast e.g. making calls to an API? Also, I noticed that there's an example section in the ballast docs but I couldn't find any links to the repository. 🤷‍♂️🏾
    c
    • 2
    • 4
  • c

    Casey Brooks

    01/11/2023, 5:26 PM
    Documentation for KVision is now added to the docs site • KVision platform page • KVision TODOMVC
    r
    • 2
    • 5
  • a

    Adrian Witaszak

    01/16/2023, 9:02 AM
    Hi. I only found out about Ballast last night and will give it a go today. The Ballast seems very nice, I like the readability it provides. In my KMM project, Android and iOS, I share UI in the
    commonMain
    using the Jetbrains Compose. Do you have any recommendations for using Ballast in this use case? Expect/Actuals for ViewModels?
    c
    • 2
    • 8
  • a

    Adrian Witaszak

    01/16/2023, 7:07 PM
    Navigation. Are we supposed to have one big router for handling the whole navigation in the app or multiple small routers?
    c
    • 2
    • 1
  • a

    Adrian Witaszak

    01/17/2023, 9:21 AM
    I migrated my app from MVIKotin and Decomposed to Ballast, all in a few hours, and I'm quite impressed. Building components feels just right. It is easy to decide where to put stuff. For now, i only have like 4 of them. Router, Login, Dashboard, Product detail. Only have a simple route from Login to Dashboard, but today end of the day, i will add a few more components and will have some questions about navigation with multiple arguments, probably. Do you handle multiple nav args in any of your samples? Is there any way of accessing the router further the back stack we get? Or the only way is passing for example
    onGoBack: () -> Unit
    c
    • 2
    • 1
  • c

    Casey Brooks

    01/20/2023, 4:43 PM
    Hey everyone, I’m looking to make some improvements to the SavedStateAdapter such that you could send multiple Inputs and/or Events after the State has been restored, but I’m not sure the best DSL to use for this. I’d love to get some feedback on the potential ways this could be implemented, and votes on which option you’d prefer. My suggestions are in the 🧵, but feel free to make other suggestions.
    r
    a
    • 3
    • 5
  • a

    Adrian Witaszak

    02/13/2023, 10:31 AM
    Hi. I've got an issue with my text field adding extra characters. Originally posted here but moved it to GH. https://github.com/copper-leaf/ballast/issues/40
    CleanShot 2023-02-13 at 10.27.45.mp4
    c
    • 2
    • 8
  • a

    Adrian Witaszak

    02/13/2023, 2:59 PM
    BTW i'm introducing ballast at work as a state management library in Android and iOS KMM project with shared UI Compose-JB 🙂 We won't be using it in the current production app (yet) because they have already invested a lot of time in React Native 😕 , but we will be using it for our internal testing app, which may replace the prod app in the future (hopefully). We still need to do a bit of testing, with Compose-jb mainly.
    c
    • 2
    • 1
  • a

    Adrian Witaszak

    02/13/2023, 3:03 PM
    The above issue was the only issue I noticed so far. I'm still working on my own KMM project on the side. Ktor backend, Android, iOS, Desktop and Web. i share my components/features with all targets, thanks to Ballast 🙂
  • a

    Adrian Witaszak

    02/13/2023, 3:06 PM
    In my component, usually, the Inputs file gets quite long. I already use separate use cases to make it shorter. What's your recommended way of keeping logic in Ballast components?
    c
    • 2
    • 3
  • a

    Adrian Witaszak

    02/13/2023, 3:09 PM
    Just thought that Inputs could take a function as a parameter, then I could keep logic in the VM, and inputs could handle... Inputs only. Right now, all VMs have no body.
    c
    • 2
    • 2
  • a

    Adrian Witaszak

    02/13/2023, 3:56 PM
    current hierarchy of my app starts with: • Root - I use for initialising Koin and passing RootContent in targets • Router - does routing ofc and runs scope in VM for monitoring Auth state. if logged out it tells router to go back to login page • Login page • rest of the app Is it ok to keep the observe user state logic in the Router's VM, or should I move it up one level? Currently the root is not a ballast component.
    c
    • 2
    • 2
  • a

    Adrian Witaszak

    02/13/2023, 3:56 PM
    I give it a try
  • a

    Adrian Witaszak

    02/13/2023, 3:58 PM
    Make's sense because there is no way of adding extra inputs to the router just to do that, and i dont we should anyway. Router should do routing only.
  • a

    Adrian Witaszak

    02/13/2023, 8:19 PM
    Creating infinite flow. I get
    20:15:18.730  W  BallastException(_cause=java.lang.IllegalStateException: This InputHandlerScope has already been closed, handled=true, latestState=State(isUserSignedIn=false), inputSequence=[src.txconnected.mobox.shared_ui.component.root.RootContract$Inputs$ObserveUserState@ce9ec24])
    Here is my input:
    RootContract.Inputs.ObserveUserState -> observeFlows(
                "observeUserState",
                flow {
                    while (true) {
                        postInput(RootContract.Inputs.CheckUserState)
                    }
                }
            )
    
            RootContract.Inputs.CheckUserState -> postInput(
                RootContract.Inputs.ChangeUserSignInState(
                    SDK.sessionManager.isLoggedIn
                )
            )
    
            is RootContract.Inputs.ChangeUserSignInState -> updateState { 
                it.copy(isUserSignedIn = input.newState) 
            }
        }
    And i start it in the RootContent:
    internal fun RootContent(
    ) {
        val coroutineScope = rememberCoroutineScope()
        val snackbarHostState = remember { SnackbarHostState() }
        val vm = remember(coroutineScope) {
            RootViewModel(
                viewModelCoroutineScope = coroutineScope,
                displayErrorMessage = { snackbarHostState.showSnackbar(it) },
            )
        }
        val state by vm.observeStates().collectAsState()
        vm.trySend(RootContract.Inputs.ObserveUserState)
        RouterContent(state.isUserSignedIn)
    }
    In router gets false will got back to Login page:
    internal fun RouterContent(isSignedIn: Boolean) {
        val scope = rememberCoroutineScope()
        val router: Router<RouterScreens> = remember(scope) {
                RouterViewModel(scope,)
            }
        val routerState: Backstack<RouterScreens> by router.observeStates().collectAsState()
    
        if (!isSignedIn) {
            router.trySend(RouterContract.Inputs.ReplaceTopDestination(
                RouterScreens.Login.matcher.routeFormat
            ))
        }
    c
    • 2
    • 5
  • a

    ayodele

    02/13/2023, 8:37 PM
    I just migrated from OrbitMVI to Ballast. In 3mins. I like the "it just works" nature. Kudos. I'm moving onto navigation with Ballast. If I'm not mistaken, it's built ontop on the redo and undo lib by the same author. My question is do I still need compose navigation with Ballast navigation? If yes does ballast handle backstack??
    c
    • 2
    • 4
  • a

    Adrian Witaszak

    02/13/2023, 11:08 PM
    Noticed that restoring the state in SavedStateAdapter is visibly slow. When the screen loads I can see text fields populating and tabs switching. Works fine when setting state values from preferences.
    c
    • 2
    • 1
  • a

    Adrian Witaszak

    02/13/2023, 11:14 PM
    CleanShot 2023-02-13 at 23.12.58.mp4
    CleanShot 2023-02-13 at 23.12.58.mp4
  • a

    Andromadus Naruto

    02/14/2023, 11:06 PM
    Hi. I used Ballast (Core & Navigation) in this project and I would like your feedback regarding its usage including any criticisms and suggestions. Thanks.
    c
    • 2
    • 2
  • a

    abbic

    02/19/2023, 8:48 PM
    hey all, when i try to begin writing
    class RouterViewModel(
        viewModelCoroutineScope: CoroutineScope
    ) : BasicRouter<AppRoutes>(config = BallastViewModelConfiguration.Builder())
    there's an error on BasicRouter because the <init> is private on BasicViewModel. additionally it claims to not find the config field. Clearly this is strange as BasicViewModel has a public secondary constructor defined right there where i can see it. am on ballast 2.3.3
    c
    • 2
    • 9
  • a

    abbic

    02/20/2023, 4:39 PM
    anyone consider making some dsl wrapper for the builders used in ballast? feels funny to see Builder patterns about when i would expect something more like
    config = viewModelConfig {
        withRouter(...)
    }
    just as an example
    c
    • 2
    • 3
  • a

    abbic

    02/20/2023, 7:03 PM
    here i am with more questions. just want to be cautious, i am planning to implement a provider for the coroutine scope with koin like so
    single { CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + SupervisorJob()) }
    that should make it easy to similarly provide ballast components with koin, which require this coroutine scope? im worrying because it seems like compose scope is great for managing the lifecycle of components like viewmodels already (leaving the composition discards the instance), so maybe koin is overkill for this
    c
    • 2
    • 6
  • a

    abbic

    02/20/2023, 10:10 PM
    another q! im trying to implement my first viewModel, and linking it up with navigation isnt so clear. my instinct is to pass the router to the EventHandler, but that means passing it through a bunch of constructors and params which doesnt feel good. another thing is an event handler having access to the whole router means you lose control of what navigation events the screen has access to. the example on the website addresses the second point, and suggests passing the navigation event through a Screen callback
    PostListScreen(
                            sort = sort,
                            onPostSelected = { postId: Long ->
                                // The user selected a post within the PostListScreen. Generate a URL which will match
                                // to the PostDetails route, by using its directions to ensure the right parameters are
                                // provided in the URL
                                router.trySend(
                                    RouterContract.Inputs.GoToDestination(
                                        AppScreen.PostDetails
                                            .directions()
                                            .pathParameter("postId", postId.toString())
                                            .build()
                                    )
                                )
                            },
                        )
    and that could work, in fact i do something very similar on android, but it doesnt feel idiomatic to ballast? for example if we wanted to navigate not directly from a ui click (and in fact, from what i understand of ballast, it would be weird to drive anything from the ui except an
    Input
    anyway), but instead drive a navigation event from business logic, we would still have to pass this navigation lambda to the event handler manually. should i provide the router through a
    single {}
    and inject it into the event handler? maybe with an interface that only exposes navigation routes available on this screen?
    c
    • 2
    • 5
  • a

    abbic

    02/25/2023, 11:12 AM
    hi, just occurred to me, is the coroutine we pass to ballast ViewModels used solely for lifecycle control? I have my Router set up to be injected by Koin as a single, but for this reason its not really possible to pass it the coroutineScope remembered at the app Composable level, and instead i just have a factory method for the scope. facing this question again for the repositories so i figure now's the time to get this right for me. @Andromadus Naruto’s repo was an interesting example, where the "applicationScope" provided is thus
    val AppScope = CoroutineScope(window.asCoroutineDispatcher())
    which is a browser thing, but it also makes me wonder what would happen if this coroutine was cancelled for any reason (at a guess, the window as coroutine dispatcher prevents that from happening?)
    c
    • 2
    • 4
  • r

    rocketraman

    02/27/2023, 8:03 PM
    Is there a way to explicitly cancel a side job? I could create a new one that does nothing with the same key but that's a bit ugly.
    c
    • 2
    • 1
  • a

    abbic

    03/01/2023, 12:35 PM
    hey hi, the project im working on is an incremental game (think cookie clicker) so theres going to be a fair amount of time based logic, like production of resources per second on an update loop. the way ballast has me set up im struggling to conceptualise any kind of classic game loop where i have delta time between updates, because there are so many suspend functions and indirect Event dispatching, potentially across multiple repos, it would for example be hard for me to figure out when a state-wide update has been successfully completed. any idea how to tame this kind of logic?
    c
    • 2
    • 6
  • r

    rocketraman

    03/17/2023, 5:36 PM
    Linking ballast-debugger doesn't work in kotlin/js due to https://kotlinlang.slack.com/archives/C01F2HV7868/p1673962920442209?thread_ts=1673905057.816579&amp;cid=C01F2HV7868 -- any plans to release a new version of ballast combined against 1.8 @Casey Brooks?
    c
    • 2
    • 6
Powered by Linen
Title
r

rocketraman

03/17/2023, 5:36 PM
Linking ballast-debugger doesn't work in kotlin/js due to https://kotlinlang.slack.com/archives/C01F2HV7868/p1673962920442209?thread_ts=1673905057.816579&amp;cid=C01F2HV7868 -- any plans to release a new version of ballast combined against 1.8 @Casey Brooks?
c

Casey Brooks

03/17/2023, 6:03 PM
Hmm, that’s disappointing that Kotlin/JS libraries aren’t forward-compatible. I haven’t upgraded any of my projects to 1.8 yet, and didn’t notice this issue yet. I am currently working on a major release, and was planning the update to Kotlin 1.8.0 to also go in Ballast 3.0.0. I was also considering doing these 3.0 breaking changes still on Kotlin 1.7 to maximize backward compatibility and ease transition, then follow it up quickly with a bump to Kotlin 1.8. I don’t have an estimate yet for when 3.0.0 will be ready, though. Regardless, I’ll cut a special release soon to compile the current 2.3.0 version against Kotlin 1.8.0, and figure out a permanent strategy for Ballast 3.0.0 and Kotlin 1.8 later.
r

rocketraman

03/17/2023, 6:14 PM
Yes it is disappointing. And the failure mode is terrible.
Kotlin is supposed to be forward compatible to two major versions, but I guess the Kotlin/JS team hasn't stuck to that
c

Casey Brooks

03/17/2023, 6:19 PM
I don’t think I’ve specifically seen that “two major versions” compatibility, maybe that’s only for JVM, or only for Stable components? There’s still a lot of non-stable components to MPP. and Kotlin/JS is supposed to be stable from 1.8+ so hopefully they will be able to stick to that promise there. But unfortunately, Native is still in Beta, so until everything is stable there really are no guarantees, and libraries will need to explicitly support each version on all targets. Definitely makes library maintenance more of a burden than I would like
r

rocketraman

03/17/2023, 6:21 PM
Yep, from https://kotlinlang.org/docs/kotlin-evolution.html#evolving-the-binary-format:
Please note that not all target platforms have reached this level of stability (but Kotlin/JVM has).
As you say, hopefully that will change moving forward.
View count: 2