Open andrey-shikhov opened 6 years ago
This seems like a feature that should wait for inline classes in Kotlin 1.3 such that we can make the types of these properties zero-overhead wrappers around Resources
such that the resulting code doesn't allocate.
How about this
fun Context.getColorCompat(@ColorRes colorInt: Int) : Int =
ContextCompat.getColor(this, colorInt)
Edit: Never mind. ContextCompat is from support library.
To minimize allocation, 1) we can reuse object per block(for example it is onCreateView method of Fragment) 2) we can make singleton object with application context to avoid activity context leak. For first case we can do something like that: client code:
fun onCreateView(...) {
with(context.properties) {
val color = colors[R.color.color_sample]
...
}
}
Implementation:
class Properties(val context: Context) {
inner class Colors {
operator fun get(@ColorRes id: Int) = ContextCompat.getColor(context, id)
}
val colors = Colors()
}
var Context.properties: Properties
get() = Properties(this)
private set(value) {}
That assumes people will use it in that manner. And in the case where they only want a single resource the allocations have jumped to 2 and the calling semantics are worse:
val color = context.properties.colors[R.color.color_sample]
I'd rather wait for inline classes before trying this out.
In my project, I've written a lot of extensions for accessing resources in property alike manner, for example: 1) Getting color: Origin:
val color = ContextCompat.getColor(context, R.color.color_sample)
Result:val color = context.colors[R.color.color_sample]
Implementation:
Same way I did with dimensions, integers, strings, animations, layouts etc. So far, so good. Also for drawables I use unchecked cast to eliminate explicit drawable cast(not safe, but at least no boilerplate which also is not safe anyway) Origin:
val shapeDrawable = ContextCompat.getDrawable(context, R.drawable.drawable_sample) as ShapeDrawable
Result:val shapeDrawable:ShapeDrawable = context.drawables[R.drawable.drawable_sample]
Note: explicit drawable type required only for local variable, if drawable declared as property of view it also can be omitted. Implementation: