Estoy un poco confundido con estas dos API.
ResourcesCompat.getDrawable(Resources res, int id, Resources.Theme theme)
Devuelve un objeto dibujable asociado con un ID de recurso en particular y con estilo para el tema especificado. Se devolverán varios tipos de objetos según el recurso subyacente, por ejemplo, un color sólido, una imagen PNG, una imagen escalable, etc.
Antes del nivel de API 21, el tema no se aplicará y este método simplemente llama a getDrawable(int).
AppCompatResources.getDrawable(Contexto contexto, int resId)
Devuelve un objeto dibujable asociado con un ID de recurso en particular.
Este método admite la inflación de recursos de vectores y vectores animados en dispositivos donde el soporte de la plataforma no está disponible.
Aquí está mi comprensión después de algunas pruebas
ContextCompat.getDrawable(@NonNull Context context, @DrawableRes int resId) ResourcesCompat.getDrawable(@NonNull Resources res, @DrawableRes int id, @Nullable Theme theme) AppCompatResources.getDrawable(@NonNull Context context, @DrawableRes int resId) VectorDrawableCompat.create(@NonNull Resources res, @DrawableRes int resId, @Nullable Theme theme Lo primero que se ve es VectorDrawableCompat y ResourcesCompat puede tener un tema específico
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); en onCreated de la clase de aplicación
1) Para imagen vectorial
API >= 21
ContextCompat funciona bienResourcesCompat funciona bienAppCompatResources funciona bienVectorDrawableCompat funciona bienAPI < 21
ContextCompatResourcesCompatAppCompatResources funciona bienVectorDrawableCompat funciona bien2) Para imagen normal
ContextCompat funciona bienResourcesCompat funciona bienAppCompatResources funciona bienVectorDrawableCompat AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); en onCreated de la clase de aplicación
1) Para imagen vectorial
ContextCompat funciona bienResourcesCompat funciona bienAppCompatResources funciona bienVectorDrawableCompat funciona bien2) Para imagen normal
ContextCompat funciona bienResourcesCompat funciona bienAppCompatResources funciona bienVectorDrawableCompatMirando el código fuente de los dos métodos, parecen muy similares. Si no tiene vectores, probablemente podría salirse con la suya usando uno u otro.
ResourcesCompat.getDrawable() llamará a Resources#getDrawable(int, theme) en API 21 o superior. También es compatible con las API de Android 4+. No es más que esto:
public Drawable getDrawable(Resources res, int id, Theme theme) throws NotFoundException { final int version = Build.VERSION.SDK_INT; if (version >= 21) { return ResourcesCompatApi21.getDrawable(res, id, theme); } else { return res.getDrawable(id); } } Where-in ResourcesCompatApi21 simplemente llama a res.getDrawable(id, theme) . Esto significa que no permitirá que se dibujen elementos de diseño vectoriales si el dispositivo no admite elementos de diseño vectoriales. Sin embargo, le permitirá pasar un tema.
Mientras tanto, el cambio de código para AppCompatResources.getDrawable(Context context, int resId) eventualmente llega a esto:
Drawable getDrawable(@NonNull Context context, @DrawableRes int resId, boolean failIfNotKnown) { checkVectorDrawableSetup(context); Drawable drawable = loadDrawableFromDelegates(context, resId); if (drawable == null) { drawable = createDrawableIfNeeded(context, resId); } if (drawable == null) { drawable = ContextCompat.getDrawable(context, resId); } if (drawable != null) { // Tint it if needed drawable = tintDrawable(context, resId, failIfNotKnown, drawable); } if (drawable != null) { // See if we need to 'fix' the drawable DrawableUtils.fixDrawable(drawable); } return drawable; } Entonces, esta instancia intentará dibujar el recurso si puede; de lo contrario, buscará en la versión ContextCompat para obtener el recurso. Entonces incluso lo teñirá si es necesario. Sin embargo, este método solo es compatible con API 7+.
Así que supongo que para decidir si deberías usar cualquiera,
¿Tiene que admitir API 4, 5 o 6?
ResourcesCompat o ContextCompat .¿Es absolutamente necesario proporcionar un tema personalizado?
ResourcesCompatAppCompatResources ResourcesCompat , ContextCompat y prácticamente cualquier clase de support-v4 que termine en Compat le evita escribir if (Build.VERSION.SDK_INT >= X) verifica en todas partes. Eso es todo. Por ejemplo en lugar de
final Drawable d; if (Build.VERSION.SDK_INT < 21) { // Old method, drawables cannot contain theme references. d = context.getResources().getDrawable(R.drawable.some_image); } else { // Drawables on API 21 can contain theme attribute references. // Context#getDrawable only exists since API 21. d = context.getDrawable(R.drawable.some_image); }puedes escribir
final Drawable d = ContextCompat.getDrawable(context, R.drawable.some_image);Se aplican los límites descritos en los comentarios, por ejemplo
// This line is effectively equivalent to the above. ResourcesCompat.getDrawable(context.getResources(), R.drawable.some_image, context.getTheme());en realidad no aplica los atributos del tema antes de Lollipop (esto se dice en la documentación). Pero no tiene que escribir if checks y su código no falla en dispositivos antiguos porque en realidad no está usando nuevas API allí.
AppCompatResources , por otro lado, lo ayudará a traer nuevas funciones a las plataformas antiguas (vectores de soporte, referencias de temas en listas de estado de color).
¿Cuál debo preferir a otro y por qué?
Use AppCompatResources para obtener resultados consistentes con el resto de la biblioteca appcompat-v7. Obtendrás:
getColorStateList que puede resolver colores con referencias de atributos de tema (como android:alpha="?android:disabledAlpha" ),getDrawable que admite vectores inflados en todas las plataformas y estos elementos vectoriales también comprenden las referencias de atributos de temas (p. ej., android:tint="?colorControlNormal" ),ContextCompat de todos modos.