I'm a bit confused with these two APIs.
ResourcesCompat.getDrawable(Resources res, int id, Resources.Theme theme)
Return a drawable object associated with a particular resource ID and styled for the specified theme. Various types of objects will be returned depending on the underlying resource -- for example, a solid color, PNG image, scalable image, etc.
Prior to API level 21, the theme will not be applied and this method simply calls through to getDrawable(int).
AppCompatResources.getDrawable(Context context, int resId)
Return a drawable object associated with a particular resource ID.
This method supports inflation of vector and animated-vector resources on devices where platform support is not available.
Question
- What is the significant difference between these two classes (besides vector inflation)?
- Which one should I prefer to another and why?
Here is my understand after some test
The first thing see is
VectorDrawableCompat
andResourcesCompat
can specific themeI) Without using
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
inonCreated
of Application class1) For vector image
API >= 21
ContextCompat
work wellResourcesCompat
work wellAppCompatResources
work wellVectorDrawableCompat
work wellAPI < 21
ContextCompat
crashResourcesCompat
crashAppCompatResources
work wellVectorDrawableCompat
work well2) For normal image
ContextCompat
work wellResourcesCompat
work wellAppCompatResources
work wellVectorDrawableCompat
crashII) Using
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
inonCreated
of Application class1) For vector image
ContextCompat
work wellResourcesCompat
work wellAppCompatResources
work wellVectorDrawableCompat
work well2) For normal image
ContextCompat
work wellResourcesCompat
work wellAppCompatResources
work wellVectorDrawableCompat
crashLooking at the source code of the two methods, they seem very similar. If you don't have vectors, you could probably get away with using either one or the other.
ResourcesCompat.getDrawable()
will callResources#getDrawable(int, theme)
on APIs 21 or greater. It also supports Android APIs 4+. It is no more than this:Where-in
ResourcesCompatApi21
merely callsres.getDrawable(id, theme)
. This means it will not allow vector drawables to be drawn if the device does not support vector drawables. It will, however, allow you to pass in a theme.Meanwhile, the code change for
AppCompatResources.getDrawable(Context context, int resId)
eventually lands to this:So this instance it will attempt to draw the resource if it can, otherwise it looks in the
ContextCompat
version to get the resource. Then it will even tint it if necessary. However, this method only supports API 7+.So I guess to decide if you should use either,
Do you have to support API 4, 5, or 6?
ResourcesCompat
orContextCompat
.Do you absolutely need to supply a custom Theme?
ResourcesCompat
AppCompatResources
ContextCompat
ResourcesCompat
,ContextCompat
and pretty much any class from support-v4 ending withCompat
saves you from writingif (Build.VERSION.SDK_INT >= X)
checks everywhere. That's it. For example instead ofyou can write
The limits described in comments apply, for example
does not actually apply the theme attributes before Lollipop (this is said in the documentation). But you don't have to write if checks and your code does not crash on old devices because you're not actually using new APIs there.
AppCompatResources
AppCompatResources
on the other hand will actually help you bring new features to old platforms (support vectors, theme references in color state lists).Use
AppCompatResources
to get consistent results with the rest of appcompat-v7 library. You'll get:getColorStateList
which can resolve colors with theme attribute references (such asandroid:alpha="?android:disabledAlpha"
),getDrawable
which supports inflating vectors on all platforms and these vector drawables also understand theme attribute references (e.g.android:tint="?colorControlNormal"
),ContextCompat
anyway.