https://kotlinlang.org logo
Docs
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
compose
  • m

    myanmarking

    12/07/2022, 10:33 AM
    is it me or latest compose version broke animations api ?
    z
    1 reply · 2 participants
  • m

    Mehdi Haghgoo

    12/07/2022, 10:51 AM
    Hey @Doris Liu are there any samples of how to use low-level animation APIs like Animation,
    animate
    and
    AnimationState
    ?
    d
    4 replies · 2 participants
  • c

    chanjungskim

    12/07/2022, 11:37 AM
    How can I align composable function????
  • c

    chanjungskim

    12/07/2022, 11:38 AM
    Modifier.align() has red line...
    r
    11 replies · 2 participants
  • e

    Elio Maroun

    12/07/2022, 11:53 AM
    https://stackoverflow.com/questions/68857820/how-to-share-a-viewmodel-between-two-or-more-jetpack-composables-inside-a-compos
  • e

    Elio Maroun

    12/07/2022, 11:54 AM
    Hello , does SaveStateHandle do the same job? So we can use the ViewModel in the last saved state in another screen ??
  • i

    Issa

    12/07/2022, 12:41 PM
    In a nested lists
    LazyColumn
    of
    LazyRow
    items, it seems that the items of each
    LazyRow
    does not keep the values of any
    remember
    function across composition if the list is scrolled vertically. Is this a known issue?
    z
    z
    5 replies · 3 participants
  • m

    myanmarking

    12/07/2022, 1:52 PM
    How to use AnimatedContent to animate text changes, but also animate the initial value?
    d
    3 replies · 2 participants
  • t

    Tower Guidev2

    12/07/2022, 2:38 PM
    good afternoon composing team... is it possible to share a compose navigation graph between multiple Activities? my application has two acitvities that i wish to use the same nav graph. I have a main Home screen which is used for the majority of user triggered interactions however my app is also accessed via local notifications where i deeplink into another Activity which all works fine, however when the user clicks BACK or UP they are returned to the device Home Page where i wish for them to stay in my application
    p
    3 replies · 2 participants
  • l

    Landry Norris

    12/07/2022, 2:45 PM
    Do we know if they’re planning on building something like ImageComposeScene for Android? I need to render a Composable directly to a Bitmap. I’m aware of the workaround of creating a ComposeView and using the old View way of drawing to a bitmap, but is there a pure compose way to do this?
  • f

    filipegoncalves

    12/07/2022, 8:45 PM
    Hello, I would like to have a
    LazyRow
    , but with two specific requirements: 1. start centered on the 2nd element (I can scroll to it, but i would need some callback regarding the visible/centered element to be able to keep state after scroll) 2. the centered element should be slightly bigger than the rest (to be highlighted). But I have absolutely no idea how to do this. Do any of you have any idea or can you give me any tip on how to advance? Image added below to show the desired view
    k
    3 replies · 2 participants
  • f

    filipegoncalves

    12/07/2022, 8:49 PM
  • c

    Colton Idle

    12/07/2022, 9:06 PM
    Some compose updates dropped today: Version 1.3.2 Stable released today. As far as I can see, nothing really tangible released. Should be an uneventful version bump. Version 1.4.0-alpha03 released today. LOTS of really cool changes! • Some animation updates, mostly related to testing it looks like? • Introduce
    HorizontalPager
    and
    VerticalPager
    , a way of showing composables in a Pager manner. Introduced
    PagerState
    to control the Pagers as well as query information about the Pager's current state. Introduced
    PageSize
    , a way of controlling the size of a Pager's page, this can be used to create a carousel like Pagers. Introduced
    PagerSnapDistance
    , a way to control how snapping will work in Pager's fling behavior. (I01120) • Introduced an overload in
    SnapFlingBehavior.performFling
    to help to understand where the fling will settle. (I569f6) • ^^ So it looks like accompanist pager is basically not needed anymore? cc: Chris banes? • Removed
    OverscrollEffect#isEnabled
    . • Added
    ScrollableState#canScrollForward
    and
    ScrollableState#canScrollBackward
    to query whether a
    ScrollableState
    has room to scroll in either direction • Added an Modifier API to query ancestors scroll info. (I2ba9d, b/203141462) • Used in
    Clickable
    to correctly delay press interactions, when gestures could become scroll events. • Fixed
    Clickables
    not correctly delaying ripples, when used inside an
    Scrollable ViewGroup
    . • Updated Drawers and Sheets to correctly delay presses in case gestures can become scroll events. • Update
    snapStepSize
    naming to be consistent with other methods in
    SnapLayoutInfoProvider
    . (Ife67c) • Added
    EmojiCompat
    to
    Compose
    (Ibf6f9, b/139326806) • Renamed
    consumedWindowInsets()
    to
    consumeWindowInsets()
    and
    withConsumedWindowInsets()
    to
    onConsumedWindowInsetsChanged()
    and made the Modifiers public. (Ie44e1) • Added
    EmojiCompat
    to
    Compose
    WOOO • Adding
    @JvmDefaultWithCompatibility
    annotation (I8f206) • Incorporated changes in the
    Swipeable
    APIs in
    ModalDrawer
    . `DrawerState`'s
    animateTo
    has been replaced by the
    open
    and
    close
    methods and the offset is now nullable. Use
    requireOffset
    to require the offset. (I3de9e) • Updated Drawers and Sheets to correctly delay presses in case gestures can become scroll events. • Fixed an issue where
    PullRefreshIndicator
    could get stuck after
    onRefresh
    is called, if the refreshing state was not changed to true. (Ie2416, b/248274004) • Add new default content padding for text button with icon to use. (I8f662) • Added disabled colors for navigation bar and rail. (Ia7892, b/258867034) • Snapshot apply notifications are now sent after the
    Recomposer
    finishes applying changes. (Iad6c0, b/222093277) • Added new wallpaper parameter to
    @Preview
    for dynamic colour support (I9f512) • Introduced changes in
    captureToImage
    to allow for capturing multi window screenshots. This is useful for screenshot tests that use compose PopUps. (I169c5)
    b
    c
    +1
    5 replies · 4 participants
  • c

    chanjungskim

    12/08/2022, 5:29 AM
    Hi, I have a question for Scrollable View vertically.
    d
    3 replies · 2 participants
  • p

    PHondogo

    12/08/2022, 8:46 AM
    Hi! Is there any Compose libraries for working with 3d graphics?
    z
    m
    2 replies · 3 participants
  • k

    Khan

    12/08/2022, 11:54 AM
    Hi. Is there a way in Compose to pass a container to another method and inflate stuff under that like for ViewGroup in xml
    viewGroup.addView()
    ViewGroup is passed to the method and i am using it as a container now to add more elements. Can i do similar thing in Compose? What i want to achieve is inflate my compose content under Toolbar (which is already created and the dynamic content needs to be added under that in later stage based on conditions and states)
    c
    1 reply · 2 participants
  • k

    kenkyee

    12/08/2022, 12:09 PM
    Will there ever be a compose BOM for the alpha releases?
  • a

    Ahaisting

    12/08/2022, 2:23 PM
    I’m trying to display dates in either 24 or 12 hour format based on user’s locale and preferences, but I’m noticing that changing date format in settings doesn’t cause a recomposition like I would expect… I tried reading
    LocalConfiguration.current
    like
    resources()
    does (https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/Resources.android.kt;l=31-34?q=Resources.android) and I have
    configChanges
    added to manifest.
    @Composable
    fun LocalDateTime.localized(): String {
        LocalConfiguration.current // was hoping this would recompose when it changes, like resources() call
        LocalContext.current // same here
        val pattern = if (DateFormat.is24HourFormat(LocalContext.current)) {
            "H:mm"
        } else {
            "h:mm a"
        }
        // format the date:
    anyone have any ideas?
    a
    a
    5 replies · 3 participants
  • p

    Pablo

    12/08/2022, 3:15 PM
    Hi, how can I position a composable view at a percentage height of a composable container view? For example, centering a Text at the 20% of the height of its container.
    k
    z
    +2
    10 replies · 5 participants
  • e

    Eric Ampire [MOD]

    12/08/2022, 6:19 PM
    Hey folk, is there any particular reason Jetpack Compose animations is not affected by these configurations from the Developers Options?
    d
    3 replies · 2 participants
  • f

    francisco

    12/08/2022, 6:28 PM
    Hello! I am trying to write a compose test that toggles the selectable state of a selection chip. The selection state is handled outside the chip and would like to toggle it on the test rule. Currently
    performClick
    is not toggling the state. Do you have suggestions? Thank you! found the issue: I was not passing
    selected
    to the chip. 🤦
    Perform_click_on_a_selectable_component.cpp
    1 reply · 1 participant
  • p

    Pablichjenkov

    12/08/2022, 10:33 PM
    In the thread code, why I get a warning about returning a State without using remember?
    Creating a state object during composition without using remember
    d
    5 replies · 2 participants
  • x

    xxfast

    12/09/2022, 12:03 AM
    Ran into this issue for the first time
    Row {
      Box {
        AnimatedVisibility()
      }
    }
    this gives you an error
    'fun RowScope.AnimatedVisibility(visible: Boolean, modifier: Modifier = ..., enter: EnterTransition = ..., exit: ExitTransition = ..., label: String = ..., content: AnimatedVisibilityScope.() -> Unit): Unit' can't be called in this context by implicit receiver. Use the explicit one if necessary
    I understand that there are three
    AnimatedVisibility
    functions
    @Composable fun AnimatedVisibility
    @Composable fun RowScope.AnimatedVisibility
    @Composable fun ColumnScope.AnimatedVisibility
    But how do I invoke the first one without any scope?
    a
    a
    3 replies · 3 participants
  • e

    eygraber

    12/09/2022, 5:52 AM
    I currently have the following composable:
    @Composable
    fun ColorPicker(
      modifier: Modifier = Modifier
    ) {
      BoxWithConstraints(
        modifier = modifier.aspectRatio(1F)
      ) {
        val diameter = constraints.maxWidth
        ...
      }
    }
    The problem is that it looks like if a user passes a
    Modifier
    to
    ColorPicker
    with size constraints, it would follow those. However,
    BoxWithConstraints
    uses the incoming constraints to size itself, not the constraints in its
    Modifier
    . In a case like this, should I be wrapping
    BoxWithConstraints
    in a
    Box
    that uses the
    Modifier
    parameter, or is it expected that the caller of
    ColorPicker
    should wrap it in whatever layout it needs, and set the size constraints appropriately?
    z
    d
    8 replies · 3 participants
  • l

    Lucas

    12/09/2022, 8:50 AM
    How can i avoid my image looking like the first one, when it should look like the second one? (Not the color but the "resolution") They are both the same image, but one is displayed in browser and the other one in compose
    z
    d
    +1
    3 replies · 4 participants
  • c

    Christoph Wiesner

    12/09/2022, 12:37 PM
    I’m having a
    LazyColumn
    that should be always scrolled to the bottom (chat style list) I do that with
    LaunchedEffect(listState.items) { scrollState....}
    problem is that i have a list item that changes it’s size depending on an interaction this change is not picked up, bc. the items list itself is not altered. don’t want to expose the in-memory state if the item to the list so i could listen to it on list-level. is there any other way apart from providing a scrollToBottom callback down to the item - that it can call when it’s size changes?
    c
    m
    3 replies · 3 participants
  • d

    Dave Scheck

    12/09/2022, 3:39 PM
    Hi everybody - I came across a really strange recomposition issue that I'd like to better understand. We have a minimal state class containing a simple integer and boolean
    data class ScreenState(val intValue: Int = 0, val boolValue: Boolean = false)
    We have a screen composable that uses a composable based on the state. For the example we increment the integer value within the state once per second. Note that the boolean isn't modified.
    @Composable
    fun TestScreen() {
        // Screen state managed by the composable
        val screenState = remember { mutableStateOf(ScreenState()) }
        /**
        Update the integer value of the state once per second
        Note that the boolean value is never changed and is always false
         **/
        LaunchedEffect(key1 = null) {
            while (true) {
                delay(1000)
                screenState.value = screenState.value.copy(
                    intValue = screenState.value.intValue + 1,
                )
            }
        }
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color(0xFF272727)),
            contentAlignment = Alignment.Center
        ) {
            // Simple composable that takes the state object as an input
            ContainerBox(screenState.value)
        }
    }
    The ContainterBox is an outlined column that takes the state in and uses the boolean to selectively include a composable using the integer value
    @Composable
    fun ContainerBox(value: ScreenState) {
        Column(
            modifier = Modifier
                .width(300.dp)
                .height(300.dp)
                .border(
                    border = BorderStroke(1.dp, Color(0xFF23C42A)),
                    shape = RoundedCornerShape(10.dp)
                )
                .clip(RoundedCornerShape(10.dp))
                .background(Color(0xFF75757A)),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            if (value.boolValue) {
                Text("Dynamic Text ${value.intValue}")
            } else {
                Text("Static Text")
            }
        }
    }
    The expectation is that since boolValue isn't being modified that ContainerBox wouldn't need to recompose. However, we see a recomposition every second. After quite a bit of debugging, we found the border modifier to be the culprit. If we take the border modifier out, the recomposition isn't performed until boolValue is changed. Does anybody know what about the border modifier is triggering the unneeded recompositions?
    p
    z
    6 replies · 3 participants
  • a

    Anton Afanasev

    12/09/2022, 4:05 PM
    Hi all! It seems like material3-compose went to stable (latest version is 1.0.1) But there are still stuff annotated with
    ExperimentalMaterial3Api
    like Scaffold, which makes it a little bit confusing. Is it safe to use Experimental api in prod? Are there going to be breaking changes for that api?
    f
    d
    11 replies · 3 participants
  • a

    Adel Ayman

    12/09/2022, 4:27 PM
    Is there plugin to fold widget code of compose?
    z
    j
    +3
    16 replies · 6 participants
  • o

    Othman El Jazouli

    12/09/2022, 5:09 PM
    sorry if this has been asked multiple times already - what’s the consensus on passing Serializable for compose navigation? I have some objects that don’t have unique ids and need to pass them around
    i
    c
    +2
    43 replies · 5 participants
Powered by Linen
Title
o

Othman El Jazouli

12/09/2022, 5:09 PM
sorry if this has been asked multiple times already - what’s the consensus on passing Serializable for compose navigation? I have some objects that don’t have unique ids and need to pass them around
i

Ian Lake

12/09/2022, 5:23 PM
There's been a bunch of conversations about this, yes: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1663470416972979?thread_ts=1663468627.871019&cid=CJLTWPH7S
o

Othman El Jazouli

12/09/2022, 6:19 PM
thanks! all clear!
c

Casey Brooks

12/09/2022, 6:42 PM
Yup, in my experience the main thing to help with the pattern linked in Ian’s thread is to push data shared between screens into the Repository layer. However, that layer doesn’t necessarily need to be backed by a persistent store like a SQLite database, for ephemeral data it could absolutely be cached in-memory in something like a
StateFlow
. That’s kind-of the whole point of Repository layer, that it is a place where data is stored, but the actual storage mechanism is an implementation detail. It’s not simply a wrapper over your local database
In fact, I’ve found that the same way one manages state in a reactive UI like Compose can actually be very effective for managing the data in the Repository layer too. Many folks treat the Repository layer as an abstraction over the database, basically remapping DB models “safer” UI models, but you can make much better use of it when you think of it in terms of State much like you would the UI. The only difference is just that it doesn’t render UI in itself, but it can be used to emit the non-UI State for your application in much the same way. Then you can use the same mental model for both the Repository and UI layers. For example, rather than the UI “querying” for the login state in request/response fashion, it can just passively observe the UI state as the user logs in/out. The complexity of managing the session becomes a relatively simple exercise in setting the appropriate data into a
StateFlow
. And the same idea can hold with much of the data that would be shared throughout your application, without necessarily needing to cache it in a local DB
f

Francesc

12/09/2022, 7:28 PM
if your data is stored ephemerally, that means that your app won't work properly after restoration from process death
o

Othman El Jazouli

12/09/2022, 7:32 PM
my concern is mostly around identifying that object - so if you don’t have an id, Ian mentioned you can just use the index on the list potentially - that would work in some cases but I can imagine some more complex data where that would fail
f

Francesc

12/09/2022, 7:33 PM
what I am referring to is that the solution where the data to pass to your destination is stored only in memory and the new destination retrieves that data, then this won't work after process death
you need to persist the data to survive process death
c

Casey Brooks

12/09/2022, 7:35 PM
It depends on how your app is set up to handle that case, whether you actually need to use the Android mechanism to save data after process death. I’m basing this on the problem from the linked thread, where the list of posts is fetched via GraphQL when it’s missing, rather than fetching at a specific point in time. If you keep it intentional that the list itself is ephemeral, than you shoudn’t expect it to survive process death, and the next the time app launches you just fetch it again. This is just my personal experience building apps, where honestly I’ve never found a good enough use-case to properly handle process death and manage the complexity around it; the clients I’ve worked with would rather wait and display a loader than show stale information. So just re-fetch that data if it goes missing for any reason, process-death or otherwise.
i

Ian Lake

12/09/2022, 7:35 PM
Maybe you should talk about your specific case and not in generalities if you want us to help with a specific case you have. Tell us what your data looks like, what the source of truth of your data is, who loads it, who needs to read it, etc.
As long as you can refetch after process death, that's enough to fulfill the expectation - it is apps that fail to restore at all that you want to avoid being lumped with
f

Francesc

12/09/2022, 7:38 PM
that works well when you have some id you want to use to fetch the data, from local or remote storage, but the original question refers to "some objects that don't have an id", and in that case, that would require some persistence to survive process death.
but the question is a bit too abstract
c

Casey Brooks

12/09/2022, 7:40 PM
yes, you’re right. In the case that there is no mechanism to look up a post (from memory or persistent storage), then you would need some way to persist that object though whatever the Android system is going to do it is. Storing it in a ViewModel’s
SavedStateHandle
, for example
o

Othman El Jazouli

12/09/2022, 7:40 PM
yeah exactly, because at that point, the data might come in a different order for some reason for example - so the question was what’s the practice for such cases
c

Casey Brooks

12/09/2022, 7:41 PM
That said, it’s probably not a good practice to do that, because there are so many ways that you could lose track of those objects. If the server doesn’t give you an ID, you might consider generating your own in the app itself to use as an “internal ID” and avoid many of these problems
i

Ian Lake

12/09/2022, 7:42 PM
Again, I think it is important to not talk about hypothetical cases. Tell us about the real case you have
o

Othman El Jazouli

12/09/2022, 7:42 PM
yea that’s what I would’ve gone for
okay
i

Ian Lake

12/09/2022, 7:43 PM
Tell us what your data looks like, what the source of truth of your data is, who loads it, who needs to read it, etc.
o

Othman El Jazouli

12/09/2022, 7:50 PM
so there is a list of
Coin
, and they can be either
Fiat
or
Crypto
- there are multiple api calls to construct them our usecase call doesn’t know about any of those, it just expects a list of
Coin
in compose we list them all and you can tap on a
Fiat
to view some things there are many modules involved, including one with a core compose navigation, from my current module that shows the list, I have to pass that
Fiat
object up to the compose navigation, and send it through to open a different screen
this is roughly how it looks like
i

Ian Lake

12/09/2022, 8:10 PM
This example doesn't match with what you've been talking about in this thread though, since each coin does have a unique identifier (USD, eth, etc) which seems like it would make it easy to pass to a CoinUseCase to retrieve by identifier
o

Othman El Jazouli

12/09/2022, 8:12 PM
sure, but there might be some coins with the same ticker and name, since anyone can create any coin with any name they want - like someone can create a btc/bitcoin coin and publish it
that’s why we didn’t want to rely on that info
i

Ian Lake

12/09/2022, 8:14 PM
There might be? Or there is?
o

Othman El Jazouli

12/09/2022, 8:15 PM
there is other cases where the same coin is in different blockchains - usdc on eth network and on matic for example
so 2 instances with the same name
i

Ian Lake

12/09/2022, 8:18 PM
It sounds like you already know how to tell those apart though - the unique identifier is name+network?
o

Othman El Jazouli

12/09/2022, 8:18 PM
so I guess the idea is to basically construct an ID, perhaps out of different field, I agree that one source of truth and query it
I was wondering if there was a different way
that’s why I asked about sending a serializable
i

Ian Lake

12/09/2022, 8:20 PM
Other than structuring your data correctly in the first place?
o

Othman El Jazouli

12/09/2022, 8:21 PM
that would partially need backend change and I would agree that’s not the major concern here
i

Ian Lake

12/09/2022, 8:23 PM
The previous thread did talk about how Navigation supports passing objects that exist only at the UI layer: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1657897115655109?thread_ts=1657844159.552379&cid=CJLTWPH7S
But that clearly isn't the case here now that you've talked about the specifics
o

Othman El Jazouli

12/09/2022, 8:24 PM
right, I believe part of the issue here is a bad data structure and doesn’t have much to do with actual compose
thanks a lot for the help!! much appreciated
c

Casey Brooks

12/09/2022, 8:30 PM
If the data you get from the APIs doesn’t give you reliable/stable IDs, that where generating your own comes in handy. You could create a custom “composite key”, such as name+network as Ian mentioned. And these values can even be a mix of hard-coded values and ones pulled from the API. For example, the network name might not come from the API response, but you probably have a list of network endpoints or different Service classes for each one that could be given some hardcoded String name within the app’s code. Or if there isn’t even that, just create something completely arbitrary like a UUID that you can reference, that had absolutely no relation to the actual data but still gives you a way to uniquely identify an object in your application.
p

Pablichjenkov

12/09/2022, 10:18 PM
Another alternative could be having a separate Repository that holds your App UI State. As Casey mention, repositories are being sold as pure data layer wrappers but nothing stops you for having one where you keep In-Memory data of you Application. For example, you can have a repo with a mirror of your nav-graph nodes, this nav-graph mirror only keeps specific UI data about each nav-graph node. Then let’s say, from any NavBackStackEntry1 you save ui data in the mirror node1, navigate to a different NavBackStackEntry2 and consume the data from the node1. That sort of things
i

Ian Lake

12/09/2022, 10:40 PM
I would strongly recommend against that approach, both because of the process death/recreation conversation above and because you cannot and should not try to mirror the lifetime of individual NavBackStackEntries and their state (a ViewModel created at the destination or graph level is a much better way to do that kind of in memory store that is backed by NavController's logic for when they can be reclaimed)
c

Casey Brooks

12/09/2022, 10:47 PM
Yeah, I would also suggest keeping the majority of your state in ViewModels scoped to whatever you need (the fragment, the navGraph, the composable, etc.). The Repository, then, holds onto anything that isn’t strictly related to the UI, or that needs to be shared across screens, and is more-or-less global to the application. The Repository layer can cache stuff in memory, but as Ian mentioned, it should also respect the possibility of being lost at any time due to process death. Whether that means having that data backed by a local DB, having logic to re-fetch from the API when the in-memory cache is empty, having those Repositories somehow save their state to a
SavedStateHandle
, etc.
p

Pablichjenkov

12/10/2022, 1:30 AM
I don’t mean mirror each NavBackStackEntry state but each NavDestination state. This is assuming destinations are unique across the whole App. There could be multiple navbackstactentries pointing to the same mirrored destination. But right, that will definitely won’t be process death friendly unless you persist everything in the mirror. It kind of scape the lifecycle of the main Android components Activity/Graph/NavBackStackEntry, it would be more like a Global ui state holder. So well, disregard my comment above
View count: 90