ResourcesCompat.getDrawable() vs AppCompatResources.getDrawable()

我对这两个 API 有点困惑。

ResourcesCompat.getDrawable(Resources res, int id, Resources.Theme theme)

返回与特定资源 ID 关联并针对指定主题设置样式的可绘制对象。根据底层资源,将返回各种类型的对象,例如,纯色、PNG 图像、可缩放图像等。

在 API 级别 21 之前,将不会应用主题,此方法只需调用 getDrawable(int)。

AppCompatResources.getDrawable(Context context, int resId)

返回与特定资源 ID 关联的可绘制对象。

此方法支持在没有平台支持的设备上对矢量和动画矢量资源进行膨胀。

问题

  1. 这两类(除了矢量膨胀之外)之间的显着差异是什么?
  2. 我应该更喜欢哪一个,为什么?

答案 1

以下是我经过一些测试后的理解:

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

我看到的第一件事是并且可以指定一个主题。VectorDrawableCompatResourcesCompat

I) 不使用

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);在应用程序类中onCreated

1) 用于矢量图像

  • API >= 21

  • ContextCompat效果很好

  • ResourcesCompat效果很好

  • AppCompatResources效果很好

  • VectorDrawableCompat效果很好

  • API < 21

  • ContextCompat 崩溃

  • ResourcesCompat 崩溃

  • AppCompatResources效果很好

  • VectorDrawableCompat效果很好

2) 对于普通图像

  • 在所有 API 级别中
  • ContextCompat效果很好
  • ResourcesCompat效果很好
  • AppCompatResources效果很好
  • VectorDrawableCompat 崩溃

二、使用

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);在应用程序类中onCreated

1) 用于矢量图像

  • 在所有 API 级别中
  • ContextCompat效果很好
  • ResourcesCompat效果很好
  • AppCompatResources效果很好
  • VectorDrawableCompat效果很好

2) 对于普通图像

  • 在所有 API 级别中
  • ContextCompat效果很好
  • ResourcesCompat效果很好
  • AppCompatResources效果很好
  • VectorDrawableCompat 崩溃

答案 2

看看这两种方法的源代码,它们看起来非常相似。如果您没有向量,则可能会使用其中一个。

ResourcesCompat.getDrawable() 将调用 API 21 或更高版本。它还支持Android API 4 +。它只不过是这个:Resources#getDrawable(int, theme)

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 只是调用 .这意味着如果设备不支持矢量可绘制对象,它将不允许绘制矢量可绘制对象。但是,它将允许您传入主题。ResourcesCompatApi21res.getDrawable(id, theme)

同时,AppCompatResources.getDrawable(Context context, int resId)的代码更改最终归结为:

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;
}

因此,如果可以,此实例将尝试绘制资源,否则它将在版本中查找以获取资源。然后,如有必要,它甚至会着色。但是,此方法仅支持 API 7+。ContextCompat

所以我想决定你是否应该使用任何一个,

  1. 您是否必须支持 API 4、5 或 6?

    • 是:别无选择,只能使用 或 。ResourcesCompatContextCompat
    • 否:继续转到#2。
  2. 您是否绝对需要提供自定义主题?

    • 是:别无选择,只能使用ResourcesCompat
    • 否: 使用AppCompatResources

推荐