https://kotlinlang.org logo
#orbit-mvi
Title
# orbit-mvi
k

kenkyee

10/13/2021, 7:13 PM
quick question on savedstate handling...is there a way to save only a partial bit of your viewmodel? e.g. just an ID to reload data with? or a Paging offset e.g. I didn't see anything in the API to do this...
m

Mikolaj Leszczynski

10/13/2021, 8:24 PM
There is no Orbit API for this, as we merely send the state off to be serialized using the object’s user-defined serializer (parceler). Typically one would use kotlin’s
@Parcelize
and with it you can alter the generated serializer by excluding parts of the state or completely overriding the parceler. Here’s a great article explaining how to do that and more: https://bladecoder.medium.com/a-study-of-the-parcelize-feature-from-kotlin-android-extensions-59a5adcd5909
k

kenkyee

10/13/2021, 10:17 PM
Ahh...add @IgnoredOnParcel everywhere 🙂 Is there any way to add a parcel size checker? We've had people stuff rest responses into savedstate 😔
m

Mikolaj Leszczynski

10/14/2021, 7:39 AM
@kenkyee Android has a 1MB limit runtime check which will throw an exception if this is exceeded. What would you need beyond that? I’m not sure you can alter the generated code, but you could write a lint check to make sure the only parcelable things inside your state include only e.g. primitive classes and Strings.
k

kenkyee

10/14/2021, 10:34 AM
Hmm.. Lint check is a good idea. When Android's check happens, it's usually too late because it is harder to find in the code base.
played w/ the @IgnoredOnParcel a bit and it doesn't look like a great solution because it won't work on constructor params (accessor syntax looks pretty bad if you use a regular class too)... And can't use a subclass like this that's parcelable because "container" expects a parcelable state class:
Copy code
data class Person(
    val info: PersonInfo
    val items: PagedList<Item>? = null)

@Parcelize
data class PersonInfo(
    val firstName: String,
    val lastName: String,
    val age: Int,
) : Parcelable
maybe I should back up a bit and describe a use case you've probably hit in your Babylon app?
use case for what I was trying to use it for was a PagingOffset on an infinite loading screen. So on next app resurrection, it'll load up to the point that you were at. How would you do something like this?
m

Mikolaj Leszczynski

10/15/2021, 11:32 AM
If this is a really long list (I assume yes since it’s paged) I would cache the results in the DB and load it from there. Otherwise just parcel the offset and do another network request but this can be bad for performance and data usage. Re: Parcelables You can provide your own
Parceler
to only save what you need, or worst case scenario you just have to implement the parcelable manually. Both approaches suck but it’s easier to achieve exactly what you need. I wasn’t aware of problems using
@IgnoredOnParcel
like this, it seems like a glaring omission! 🤔 Haven’t used
@Parcelize
a lot myself, so I assumed it would just work. PS We have work to do in this respect - currently we’re forcing you to use
Parcelable
which, as you can see, comes with some inherent problems… And it won’t work cross-platform which is why we need a better solution anyway.
o

Oleksii Malovanyi

10/15/2021, 12:24 PM
Just sharing the experience: we decided to use Paging 3.x lib + Compose, so it’s completely extracted out of the state: of course in this case if the process is destroyed, the scroll position is forgotten, but pros and cons we think it’s not a big deal for our use case but helps implementing it very straightforward
Anyway, in my experience, you’d never want a big list of something in your state if it’s saved to parcel -> this causes all sort of errors which extremely hard to debug due to size limit
k

kenkyee

10/15/2021, 12:31 PM
you can't just leave it in the DB e.g., with Compose. The list is part of your state. There is actually a KMP library that adds support for @Parcelable: https://github.com/icerockdev/moko-parcelize
Trying to avoid Paging Lib because the initial betas I tried were super buggy 🙂 But this isn't necessarily limited to paging...that's just an example where I wanted to save a partial state into savedstate...
Might be a good opportunity to use KSP to generate the parcelable's parcelizer? This way you could also validate that people aren't stuffing giant blobs into savedstate too.
m

Mikolaj Leszczynski

10/15/2021, 12:36 PM
you can’t just leave it in the DB e.g., with Compose. The list is part of your state.
This doesn’t mean you can’t cache it in the DB and load it from there when you restore
Might be a good opportunity to use KSP to generate the parcelable’s parcelizer? This way you could also validate that people aren’t stuffing giant blobs into savedstate too.
That’s like an entirely new parcelization library project… 😅
true story 1
o

Oleksii Malovanyi

10/15/2021, 12:38 PM
My bet is it would be extremely hard to set a limit on parcelable anyway, ’cause android has a limit on the whole parcelable for activity, and it involves a lot of view’s states, not only the one you save explicitly
k

kenkyee

10/15/2021, 12:39 PM
Devs are sometimes crazy and parcelize everything...some spots of our current codebase save off entire REST API responses 🤦
o

Oleksii Malovanyi

10/15/2021, 12:39 PM
btw, paging 3 works really nice with compose now -> at least we can’t see any problems
👍 1
7 Views