Другое

Руководство по замене Resources.getColor для Android 6.0+

Узнайте заменитель устаревшего Resources.getColor() в Android 6.0 Marshmallow. Используйте ContextCompat.getColor() и лучшие практики работы с цветами в приложениях.

Какой заменитель метода Resources.getColor(int id), который устарел в Android 6.0 Marshmallow (API 23)?

Метод Resources.getColor(int id) был объявлен устаревшим в Android 6.0 Marshmallow (API 23):

java
@ColorInt
@Deprecated
public int getColor(@ColorRes int id) throws NotFoundException {
    return getColor(id, null);
}

Что я должен использовать вместо этого устаревшего метода?

Рекомендованная замена устаревшего метода Resources.getColor(int id) в Android 6.0 Marshmallow (API 23) – это ContextCompat.getColor(Context context, int id) из Android Support Library или AndroidX, который обеспечивает обратную совместимость и корректно обрабатывает разрешение цвета с учётом темы.

Содержание


Почему был удалён метод Resources.getColor()?

Метод Resources.getColor(int id) был объявлен устаревшим в API 23 в основном из‑за того, что он не учитывает контекст текущей темы. В Material Design и современной разработке Android цвета должны разрешаться с учётом текущей темы, чтобы обеспечить визуальную согласованность на разных устройствах и при различных пользовательских настройках.

Удаление произошло, потому что оригинальный метод не учитывал контекст темы, что могло привести к неконсистентному отображению цветов на разных версиях Android и конфигурациях устройств. Без учёта темы цвета могут выглядеть иначе, чем задумано, в зависимости от настроек темы устройства.

Ключевой вывод: Разрешение цвета с учётом темы гарантирует, что цвета адаптируются к разным темам (светлая/тёмная, настройки доступности и т.д.) и сохраняют визуальную согласованность во всей экосистеме Android.


Основная замена: ContextCompat.getColor()

Самый широко используемый заменитель устаревшего метода – ContextCompat.getColor(Context context, int id). Он предоставляет несколько важных преимуществ:

Преимущества ContextCompat.getColor()

  • Обратная совместимость: Работает на всех уровнях API Android
  • Учет темы: Корректно разрешает цвета с учётом текущей темы
  • Безопасность от null: Гладко обрабатывает крайние случаи
  • Консистентное поведение: Обеспечивает единообразное поведение на разных версиях Android

Пример реализации

java
// До (устаревший в API 23+)
int color = getResources().getColor(R.color.my_color);

// После (рекомендованный подход)
int color = ContextCompat.getColor(context, R.color.my_color);

Добавление зависимости

Если вы ещё не используете Android Support Library или AndroidX, добавьте следующее в ваш build.gradle:

gradle
// Для AndroidX (рекомендовано)
implementation 'androidx.core:core-ktx:1.12.0'

// Или для устаревшей Support Library
implementation 'com.android.support:support-core-utils:28.0.0'

Альтернативный подход: Resources.getColor() с темой

Другой подход – использовать новый метод Resources.getColor(int id, Theme theme), который был введён вместе с удалением устаревшего метода. Он позволяет явно указать тему:

Использование Resources.getColor() с темой

java
// Получаем текущую тему
Theme theme = context.getTheme();

// Используем новый метод с параметром темы
int color = getResources().getColor(R.color.my_color, theme);

Когда использовать этот подход

  • Когда у вас есть специфические требования к теме
  • При работе внутри пользовательских представлений или компонентов
  • Когда нужна точная настройка разрешения цвета

Однако ContextCompat.getColor() обычно предпочтительнее для большинства случаев, так как он автоматически обрабатывает разрешение темы и обеспечивает лучшую обратную совместимость.


Примеры миграции и лучшие практики

Миграция кода Activity/Fragment

java
// В Activity или Fragment
public class MyActivity extends AppCompatActivity {
    private int primaryColor;
    private int secondaryColor;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // Заменяем устаревшие вызовы
        primaryColor = ContextCompat.getColor(this, R.color.primary_color);
        secondaryColor = ContextCompat.getColor(this, R.color.secondary_color);
        
        // Используем цвета
        textView.setTextColor(primaryColor);
        button.setBackgroundColor(secondaryColor);
    }
}

Миграция кода пользовательского представления

java
// В пользовательском представлении
public class CustomView extends View {
    private int accentColor;
    
    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    private void init() {
        // Используем ContextCompat для учёта темы
        accentColor = ContextCompat.getColor(getContext(), R.color.accent_color);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        // Используем разрешённый цвет
        paint.setColor(accentColor);
        // ... код рисования
    }
}

Лучшие практики

  1. Всегда используйте ContextCompat.getColor() при новом развитии
  2. Проводите миграцию как можно раньше – чтобы избежать технического долга
  3. Проверяйте на разных темах – чтобы убедиться в консистентности цветов
  4. Используйте атрибуты цвета в темах для динамического теминга
  5. Используйте векторные изображения с tint вместо жёстко закодированных цветов, где это возможно

Обработка разных версий Android

При поддержке широкого диапазона версий Android необходимо учитывать стратегии совместимости:

Реализация, зависящая от версии

java
public static int getColorCompat(Context context, int colorResId) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // Используем новый метод для API 23+
        return context.getResources().getColor(colorResId, context.getTheme());
    } else {
        // Используем устаревший метод для старых версий
        return context.getResources().getColor(colorResId);
    }
}

Однако такой подход не рекомендуется, поскольку он возвращает устаревший метод для старых версий. Вместо этого используйте ContextCompat.getColor(), который обрабатывает это автоматически.

Использование библиотек совместимости AndroidX

gradle
// В build.gradle
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-ktx:1.12.0'

Библиотеки AndroidX предоставляют всесторонние решения совместимости, которые автоматически обрабатывают различия версий.


Распространённые ошибки и решения

Ошибка 1: Забыли передать параметр Context

Проблема: Забыли передать Context в ContextCompat.getColor()

java
// НЕПРАВИЛЬНО – приводит к ошибке компиляции
int color = ContextCompat.getColor(R.color.my_color);

Решение: Всегда передавайте Context

java
// ПРАВИЛЬНО
int color = ContextCompat.getColor(context, R.color.my_color);

Ошибка 2: Утечки памяти в пользовательских представлениях

Проблема: Хранение ссылок на Context в пользовательских представлениях может вызвать утечки памяти

Решение: Используйте Context корректно и избегайте хранения его ненужных ссылок

java
// В пользовательском представлении – избегайте долгосрочного хранения контекста
public class SafeCustomView extends View {
    private int color;
    
    public SafeCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // Используем контекст сразу и не сохраняем его
        color = ContextCompat.getColor(context, R.color.my_color);
    }
}

Ошибка 3: Не тестировали на разных темах

Проблема: Цвета не отображаются корректно в темном режиме или других темах

Решение: Тестируйте с разными темами и используйте ресурсы, зависящие от темы

xml
<!-- В colors.xml -->
<color name="primary_color">#3F51B5</color>
<color name="primary_color_dark">#303F9F</color>

<!-- В themes.xml -->
<item name="colorPrimary">@color/primary_color</item>
<item name="colorPrimaryDark">@color/primary_color_dark</item>

Ошибка 4: Использование жёстко закодированных цветов вместо атрибутов

Проблема: Использование жёстко закодированных цветов вместо атрибутов темы

Решение: Определяйте цвета в темах и ссылайтесь на них через атрибуты

xml
<!-- В разметке -->
<LinearLayout
    android:background="?attr/colorBackground"
    android:orientation="vertical">
    
    <TextView
        android:textColor="?attr/textColorPrimary"
        android:text="Hello World"/>
</LinearLayout>

Заключение

  1. Используйте ContextCompat.getColor() как основную замену устаревшему Resources.getColor() для обеспечения обратной совместимости и учёта темы.
  2. Мигрируйте существующий код заменой всех вызовов getResources().getColor(id) на ContextCompat.getColor(context, id) чтобы избежать предупреждений компилятора и обеспечить корректное поведение на всех версиях Android.
  3. Используйте атрибуты темы (?attr/colorPrimary, ?attr/textColorPrimary) вместо жёстко закодированных ссылок на цвета для лучшей поддержки тем и консистентности.
  4. Тщательно тестируйте на разных версиях Android, темах и конфигурациях устройств, чтобы убедиться, что цвета отображаются корректно во всех сценариях.
  5. Рассмотрите использование библиотек AndroidX для всесторонних решений совместимости и постоянной поддержки, так как они предоставляют наиболее надёжный подход к управлению различиями версий в разработке Android.

Следуя этим рекомендациям, вы гарантируете, что ваше приложение сохраняет визуальную согласованность, поддерживает современные возможности теминга и остаётся совместимым с экосистемой Android.

Источники

  1. Документация Android – Resources.getColor()
  2. Документация Android – ContextCompat.getColor()
  3. Material Design – Руководство по цвету
  4. Блог Android Developers – Обновления Material Design
Авторы
Проверено модерацией
Модерация