Подтвердить что ты не робот

ResourcesCompat.getDrawable() vs AppCompatResources.getDrawable()

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

ResourcesCompat.getDrawable (Ресурсы res, int id, тема Resources.Theme)

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

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

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

Вернуть рисуемый объект, связанный с конкретным идентификатором ресурса.

Этот метод поддерживает инфляцию векторных и анимированных векторных ресурсов на устройствах, где поддержка платформы недоступна.

Вопрос

  1. Какова значительная разница между этими двумя классами (помимо векторной инфляции)?
  2. Какой из них я предпочитаю другому и почему?
4b9b3361

Ответ 1

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

ResourceCompat.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);
    }
}

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

Между тем, изменение кода для AppCompatResources.getDrawable(Context context, int resId) конечном итоге 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;
   }

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

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

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

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

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

Ответ 2

Вот мое понимание после некоторого теста

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 класса Application

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

  • API >= 21

    • ContextCompat хорошо работать
    • ResourcesCompat хорошо работает
    • AppCompatResources хорошо работает
    • VectorDrawableCompat хорошо работает
  • API < 21

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

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

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

II) Используя

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); в onCreated класса Application

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

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

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

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

Ответ 3

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

вы можете написать

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 и цвета, такие как флажки или переключатели, будут иметь правильные цвета, определяемые заданной контекстной темой,
  • Если вышеуказанное не применяется, оно все равно возвращается к ContextCompat.