ResourcesCompat.getDrawable()vs AppCompatResources.getDrawable()

azi*_*ian 26 java android android-theme android-resources android-styles

我对这两个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. 我应该选择哪一个?为什么?

Pha*_*inh 35

经过一些测试后,我才明白这一点

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
Run Code Online (Sandbox Code Playgroud)

首先看到的是可以VectorDrawableCompatResourcesCompat特定的主题

I)不使用

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

1)对于矢量图像

  • API> = 21

    • ContextCompat 工作得很好
    • ResourcesCompat 工作得很好
    • AppCompatResources 工作得很好
    • VectorDrawableCompat 工作得很好
  • API <21

    • ContextCompat 紧急
    • ResourcesCompat 紧急
    • AppCompatResources 工作得很好
    • VectorDrawableCompat 工作得很好

2)对于正常图像

  • 在所有级别
    • ContextCompat 工作得很好
    • ResourcesCompat 工作得很好
    • AppCompatResources 工作得很好
    • VectorDrawableCompat 紧急

II)使用

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

1)对于矢量图像

  • 在所有级别
    • ContextCompat 工作得很好
    • ResourcesCompat 工作得很好
    • AppCompatResources 工作得很好
    • VectorDrawableCompat 工作得很好

2)对于正常图像

  • 在所有级别
    • ContextCompat 工作得很好
    • ResourcesCompat 工作得很好
    • AppCompatResources 工作得很好
    • VectorDrawableCompat 紧急

  • 很好的总结,但不幸的是只是显示支持库有多大的混乱:).你有1002345种方法来创建drawable(动画或非动画).我们应该有一种独特的方式来做它,如果不支持动画,他们应该尝试将其转换为简单的可绘制图像,但不要使用ResourceNotFound使应用程序崩溃 (6认同)
  • 那么“AppCompatResources”是唯一没有崩溃的资源吗? (3认同)

Dee*_*eeV 26

看看这两种方法的源代码,它们看起来非常相似.如果你没有矢量,你可能会使用其中一个或另一个.

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在哪里ResourcesCompatApi21只是打电话res.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;
}
Run Code Online (Sandbox Code Playgroud)

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

所以我想决定你是否应该使用,

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

    • 是的:别无选择,只能使用ResourcesCompatContextCompat.
    • 不:继续前进#2.
  2. 你绝对需要提供自定义主题吗?

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


Eug*_*nec 10

ContextCompat

ResourcesCompat,ContextCompat和几乎所有从支持-V4结局类Compat从写为您节省if (Build.VERSION.SDK_INT >= X)到处检查.而已.例如,而不是

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);
}
Run Code Online (Sandbox Code Playgroud)

你可以写

final Drawable d = ContextCompat.getDrawable(context, R.drawable.some_image);
Run Code Online (Sandbox Code Playgroud)

例如,注释中描述的限制适用

// This line is effectively equivalent to the above.
ResourcesCompat.getDrawable(context.getResources(), R.drawable.some_image, context.getTheme());
Run Code Online (Sandbox Code Playgroud)

实际上并没有在Lollipop之前应用主题属性(这在文档中说明).但是如果检查和代码在旧设备上没有崩溃,你就不必写了,因为你实际上并没有在那里使用新的API.

AppCompatResources

AppCompatResources 另一方面,实际上将帮助您为旧平台带来新功能(支持向量,颜色状态列表中的主题引用).

我应该选择哪一个?为什么?

用于AppCompatResources与appcompat-v7库的其余部分获得一致的结果.你会得到:

  • getColorStateList可以使用主题属性引用解析颜色(例如android:alpha="?android:disabledAlpha"),
  • getDrawable它支持所有平台上的膨胀向量,这些向量drawables也理解主题属性引用(例如android:tint="?colorControlNormal"),
  • appcompat-v7 drawables和颜色,如复选标记或单选按钮,将具有由提供的上下文主题定义的正确颜色,
  • 如果以上不适用,它ContextCompat无论如何都会回落.