As a beginner I had a resource-loading related tho...
# compose
d
As a beginner I had a resource-loading related thought today. Many built-in composables accept either
ImageAsset
or
VectorAsset
(for example
Icon
). And this is done using overloads. So if my composable has
Icon
as a child and I want to make the asset which I pass to it configurable, I have to introduce 2 overloads too. And this repeats up and up. The thought was: if
ImageAsset
and
VectorAsset
had some comon supertype this would be easier. For example some kind of
sealed class Resource { class ImageAsset; class VectorAsset }
. I suspect that current state of affairs had some reasoning behind it, does anyone know more?
r
Instead of passing down the resource you can pass down a composable and let the caller setup the
Icon
however it wants. Or better it can pass something else too.
d
Yep, I thought that the API design nudges me towards this, but then I thought that if the icon is in 90% of cases set up identically it's too verbose. For example some kind of PrimaryButton from UiKit which is everywhere in the app and only icon resource gets changed.
a
You can fully create a composable say
IconifiedButton
and set the configure the common cases as you like. Now you have one
Composable
wich takes an
Icon
as a param (the one that changes) with the settings of our choosing. Makes sense? You wouldn't have to duplicate your configurations, all you'll have to do is call your
IconifiedButton
and pass the
Icon
you wanna pass
d
That's what I described above with
PrimaryButton
example. But then if 99% of usecases are interested in only changing
R.drawable.some_icon
(which can be either image or vector asset) requiring passing a whole
Icon
for that feels a bit verbose. But it's just a thought, in the end I understand that Jepack Compose is about composables, so passing an Icon is probably more idiomatic.
a
It is actually more Idiomatic yes.. Your
PrimaryButton
can even have a default
Icon
to make it simple
n
In this case there aren't much similarities between ImageAsset and VectorAsset other than being binary representations of their respective formats. However ImagePainter and VectorPainter are implementations of the Painter class which understands how to draw ImageAssets and VectorAssets accordingly. You should be able to create shared code that consumes a Painter parameter and pass in the value that way
d
Ok, thanks. Although semantically they are still both Assets. For me having
Copy code
sealed class Asset {
  data class ImageAsset(...) : Asset()
  data class VectorAsset(...) : Asset()
}
doesn't seem weird. Seems like a valid API-design choice. But I guess there were some other considerations.
n
Not all assets are the same, and there aren't any similarities in usage/consumption of these assets. In this example how is Asset any different than Any? However, Painter indicates a consistent drawing interface which allows for implementations to interpret and draw based on any data input including ImageAsset/VectorAsset
Also lends itself to more custom "Asset" implementations that can be driven externally
d
There are similarities: assets can be loaded, drawn. The very thing that word "Asset" exists in both class names indicates that they have something in common. They are differently loaded and differently drawn, so one can pattern-match using
when
in my example above. Also the fact that almost identical overloads for these assets present on
Icon
class, indicates that these are quite similar.
n
The focus is one what are the types of things you want to do with an asset vs making all assets the same. The overloads in Icon are provided as convenience. Most of the time you are interested in drawing an asset to which we abstract out the concept of something that is drawn (Painter). If you are doing something more specific with an Asset (i.e. serializing content to send over the network) you are more concerned with the concrete asset implementation. Because a Painter is decoupled from the input, you can see performance improvements with a single Painter referring to a single Asset used several times (ex star icon in a list of composables that are reused)
d
I see. I'm not against using Painter and not suggesting anything about it. I just noted that it seems like having a sealed class for assets would provide a slightly better api here, no convenience overloads would be needed: I could either use a Painter or pass an "Asset" to draw, both could be accepted by a single overload. Having an ADT for these asset types doesn't mean they are the same, it means they represent "kinds" of something, in this case — an asset.
n
The problem is that having a sealed Asset class would prevent folks from defining their own asset types. Once we allow folks to create their own Asset types they would need to define a way to draw that asset. Painter decouples the Asset data from the drawing logic and provides opportunity for object reuse and optimizations.
d
Ah, perhaps this was the reason they didn't went with the sealed class then!
r
@dimsuz Nader works on the graphics APIs of Compose 😉
d
Hah, great! I wished someone working on those APIs would explain me the reasoning and it was exlained! 👍
👍 1
r
We aim to please 🙂
😊 1