Какой Context передается в кастомную View и что он представляет
Что проверяют
Понимаете ли вы, откуда у View берётся контекст и почему от него зависят тема, ресурсы и утечки памяти. Следом часто просят достать Activity из view.context или объяснить, что будет, если создать View с applicationContext.
Как отвечать
View получает тот Context, который передали в конструктор, и хранит его всю жизнь, доступ через getContext(). Откуда он берётся:
- при инфлейте из XML: контекст того
LayoutInflater, который раздувает разметку. В Activity это сама Activity, во фрагменте контекст хост-Activity; - при
android:themeна элементе разметки: инфлейтер оборачивает контекст вContextThemeWrapperс этой темой, иcontextу такой View уже не Activity; - при создании в коде: тот, что вы передали сами, обычно
thisв Activity илиrequireContext()во фрагменте.
Что он представляет: Context это абстрактный класс, а не интерфейс, точка доступа к ресурсам, теме, системным сервисам и окружению компонента. Для View важнее всего тема: атрибуты из XML читаются через context.obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, defStyleRes), и значения вроде ?attr/colorPrimary резолвятся по теме именно этого контекста. Цвета берите через ContextCompat.getColor, getResources().getColor(int) давно устарел.
Про конструкторы: инфлейтер вызывает вариант (Context, AttributeSet), вариант с defStyleAttr нужен для стиля по умолчанию из темы. Чтобы получить Activity, контекст разворачивают циклом по ContextWrapper.baseContext. Прямое приведение context as Activity падает, как только в цепочке появилась обёртка.
Где спотыкаются
Сохраняют View или её context в синглтоне, companion object или ViewModel. Контекст View это Activity, и после поворота экрана она остаётся в памяти.
Создают View с applicationContext. Теряется тема Activity со всеми переопределениями, компоненты AppCompat и Material могут выглядеть не так или упасть с ошибкой про тему.
В Kotlin вешают @JvmOverloads на наследника Button или MaterialButton с defStyleAttr = 0. Стиль базового виджета по умолчанию пропадает, и кнопка выглядит как голый текст.