ResourcesCompat.getDrawable () vs AppCompatResources.getDrawable()

Я немного запутался с этими двумя API.

ResourcesCompat.getDrawable (Resources res, int id, Resources.Тема тема)

возвращает объект мешочки, связанного с определенным идентификатором ресурса и стиле на заданную тему. Различные типы объектов будут возвращены в зависимости от базового ресурса - например, сплошной цвет, PNG-изображение, масштабируемое изображение и т. д.

до уровня API 21, тема не будет применяться, и этот метод просто вызывает getDrawable (int).

AppCompatResources.getDrawable (контекстный контекст, int resId)

возвращает объект катры, связанного с определенным идентификатором ресурса.

этот метод поддерживает инфляции вектор и мультипликация-вектор ресурсы на устройствах с поддержкой платформы не доступный.

вопрос

  1. в чем существенная разница между этими двумя классами (кроме того!--3-->вектор инфляция)?
  2. какой из них следует предпочесть другому и почему?

3 ответов


глядя на исходный код этих двух методов, они кажутся очень похожими. Если у вас нет направления, вы можете использовать либо одно, либо другое.

ResourceCompat.getDrawable() будем называть Resources#getDrawable(int, theme) на APIs 21 или выше. Он также поддерживает Android APIs 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);
    }
}

где-в ResourcesCompatApi21 просто называет res.getDrawable(id, theme). Это означает, что это будет не разрешить рисование векторных чертежей, если устройство не поддерживает векторные чертежи. Это, однако, позволит вам перейти к теме.

между тем, изменение кода для AppCompatResources.getDrawable (контекстный контекст, 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;
   }

таким образом, этот экземпляр попытается нарисовать ресурс, если он может, иначе он выглядит в ContextCompat версия для получения ресурсов. Тогда он даже будет окрашивать его, если это необходимо. Однако, этот метод поддерживает только API 7+.

так что я думаю решить, если вы должны использовать либо

  1. вам нужно поддерживать API 4, 5 или 6?

    • Да: нет выбора, кроме как использовать ResourcesCompat или ContextCompat.
    • нет: продолжайте идти к #2.
  2. вам абсолютно необходимо предоставить пользовательскую тему?

    • Да: нет выбора, кроме как использовать ResourcesCompat
    • Нет: Использовать AppCompatResources

вот мой понимаю после некоторого теста

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

первое, что вижу-это VectorDrawableCompat и ResourcesCompat может конкретная тема

I) без использования

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); на onCreated класса приложения

1) для векторного изображения

  • API >= 21

    • ContextCompat хорошо работать
    • ResourcesCompat хорошо работать
    • AppCompatResources работа ну!--47-->
    • VectorDrawableCompat хорошо работать
  • API

    • ContextCompat авария
    • ResourcesCompat авария
    • AppCompatResources хорошо работать
    • VectorDrawableCompat хорошо работать

2) для нормального изображения

  • на всех уровнях
    • ContextCompat работа ну!--47-->
    • ResourcesCompat хорошо работать
    • AppCompatResources хорошо работать
    • VectorDrawableCompat авария

II) использовать

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); на onCreated класса приложения

1) для векторного изображения

  • на всех уровнях
    • ContextCompat хорошо работать
    • ResourcesCompat хорошо работать
    • AppCompatResources работа ну!--47-->
    • VectorDrawableCompat хорошо работать

2) для нормального изображения

  • на всех уровнях
    • ContextCompat хорошо работать
    • ResourcesCompat хорошо работать
    • AppCompatResources хорошо работать
    • VectorDrawableCompat авария

ContextCompat

ResourcesCompat, ContextCompat и практически любой класс из support-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);
}

можно писать

final Drawable d = ContextCompat.getDrawable(context, R.drawable.some_image);

применяются ограничения, описанные в комментариях, например

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

фактически не применяет атрибуты темы перед Lollipop (об этом говорится в документации). Но тебе не обязательно писать, если проверяет, и ваш код не аварийно завершает работу на старых устройствах, потому что вы фактически не используете новые API.

AppCompatResources

AppCompatResources С другой стороны, фактически поможет вам принести новые функции на старые платформы (векторы поддержки, ссылки на темы в списках состояний цвета).

какой из них следует предпочесть другому и почему?

использовать AppCompatResources чтобы получить согласованные результаты с остальной частью библиотеки appcompat-v7. Вы получить:

  • getColorStateList который может разрешать цвета со ссылками на атрибуты темы (например,android:alpha="?android:disabledAlpha"),
  • getDrawable который поддерживает раздувание векторов на всех платформах, и эти векторные чертежи также понимают ссылки на атрибуты темы (например,android:tint="?colorControlNormal"),
  • AppCompat-V7 drawables и цвета, такие как флажки или переключатели, будут иметь правильные цвета, определенные поставляемой темой контекста,
  • если вышеуказанное не применяется, то оно падает назад к ContextCompat в любом случае.