Что такое контекст? Более обширный взгляд
Стандартные библиотеки языка очень образные и что бы понять семантику контекста надо прежде всего обратиться к самому понятию «контекст» в общепринятом понимании, а не в специфике программирования: Конте́кст (от лат. contextus — «соединение», «связь») — законченный отрывок, общий смысл которого позволяет уточнить значение входящих в него отдельных слов, предложений, и т. п. _ _Говорить, опираясь на контекст, — значит придерживаться установившегося в разговоре уровня абстракции и использовать понятия заданного в нём семантического поля.
23 мар 2017 в 11:19
В более широком значении контекст — среда, в которой существует объект. С формальной точки зрения контекст представляет собой определённую систему отсчета, пространство имён. Любое событие, происходящее в жизни субъекта, интерпретируется исходя из контекста ситуации, отражённой в памяти субъекта.
23 мар 2017 в 11:19
В программировании понятие контекст имеет те же свойства и семантическую нагрузку — давать элементу переменные окружения, обуславливающие его работу
23 мар 2017 в 11:21
(: А по вопросу мне нечего ответить
23 мар 2017 в 11:22
@Tachkin, отличный ответ 🙂 Я плюсану, оформляйте. 🙂
23 мар 2017 в 11:40
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
класс Context содержит в себе всевозможную информацию о ресурсах системы, как уже было сказано в другом ответе. Конкретно в этом вопросе нас интересует, что он содержит, помимо прочего, и параметры темы (стилей) для отображения View
Почему в качестве контекста можно передать this? Это же ссылка на класс
Активити является наследником класса Context и несет в себе информацию о контексте для этой активити, поэтому мы можем использовать ссылку на именно этот класс в качестве контекста. С Fragment , к примеру, это уже не работает — он не наследуется от Context
Есть ли случаи когда надо передать именно getApplicationContext?
Тема (стиль) всего приложения и конкретной активити может отличаться (для активити в манифесте указан другой стиль). Тогда запрос контекста приложения и контекста активти вернет разное оформление View
Почему контекст нужен везде, где происходит работа с интерфейсом?
Потому что он содержит стиль для View
на остальные вопросы ответ тот же — в контексте содержится информация, как должен выглядеть View . Например, стиль кнопки темы Holo и темы AppCompat сильно отличается, в контексте и содержится эта информация.
Возможно в приложении могут существовать и какие то другие отличия в окружении, назначенном всему приложению и конкретной активити, тогда обращение к контексту приложения или активити тоже будет иметь значение, но мне такие отличия (кроме тем и стилей) припомнить не удалось.
UPD несколько важных замечаний по getApplicationContext() , не связанных с UI приложения из этой статьи
- контекст приложения следует использовать везде, где контекст необходимо передать за пределы жизненного цикла передающего компонента (в объекты, которые будут жить дольше, чем создавшая/вызвавшая их активность, например) во избежании удержания ссылки на этот компонент при использовании его собственного контекста и утечек памяти.
- во внешние библиотеки следует передавать контекст приложения по тем же причинам, что и п.1
- контекст приложения не имеет информации по особенностям GUI отдельной активити, если они отличаются от параметров всего приложения, в таких случаях нельзя использовать контекст приложения при работе с GUI этой активити.
- приложение (класс Application ) — синглтон и его контекст тоже синглтон, этот контекст может удерживать объекты с более коротким жизненным циклом и приводить к утечкам памяти, если не позаботиться о их корректной обработке GC
что такое контекст js
Контекст в JavaScript может быть не совсем очевидным понятием на старте изучения, но пример поможет лучше понять его суть.
const car = brand: 'BMW', model: 'X5', startEngine: function () console.log(`Запускаем двигатель $this.brand> $this.model>`); >, >; car.startEngine(); // Запускаем двигатель BMW X5
В данном примере car — это объект, у которого есть свойства brand и model , а также метод startEngine , который выводит в консоль сообщение о запуске двигателя. Обратите внимание на использование ключевого слова this в методе startEngine .
Когда мы вызываем метод startEngine на объекте car , контекст выполнения метода будет указывать на объект car . Это означает, что мы можем использовать ключевое слово this внутри метода, чтобы обращаться к свойствам объекта car .
Если мы попытаемся вызвать метод startEngine в контексте другого объекта, например truck , то мы получим другой результат:
const truck = brand: 'Volvo', model: 'FH16', >; car.startEngine.call(truck); // Запускаем двигатель Volvo FH16
Здесь мы использовали метод call для изменения контекста выполнения метода startEngine . Метод call позволяет вызвать функцию с указанным контекстом, который в данном случае указывается как объект truck . Теперь, когда мы вызываем startEngine в контексте объекта truck , значения свойств brand и model будут заменены на значения объекта truck , и мы получим другой результат.
Это простой пример, который демонстрирует, как работает контекст в JavaScript. Контекст позволяет функциям и методам иметь доступ к свойствам объектов и другим переменным в текущем исполнении кода. Изменение контекста выполнения функции с помощью методов call , apply и bind может быть полезным в различных сценариях программирования, когда нужно использовать функцию в контексте другого объекта.
Context
Context – это объект, который предоставляет доступ к базовым функциям приложения: доступ к ресурсам, к файловой системе, вызов активности и т.д. Activity является подклассом Context, поэтому в коде мы можем использовать её как ИмяАктивности.this (напр. MainActivity.this), или укороченную запись this. Классы Service, Application и др. также работают с контекстом.
Доступ к контексту можно получить разными способами. Существуют такие методы как getApplicationContext(), getContext(), getBaseContext() или this, который упоминался выше, если используется в активности.
На первых порах не обязательно понимать, зачем он нужен. Достаточно помнить о методах, которые позволяют получить контекст и использовать их в случае необходимости, когда какой-нибудь метод или конструктор будет требовать объект Context в своих параметрах.
В свою очередь Context имеет свои методы, позволяющие получать доступ к ресурсам и другим объектам.
- getAssets()
- getResources()
- getPackageManager()
- getString()
- getSharedPrefsFile()
Возьмём к примеру метод getAssets(). Ваше приложение может иметь ресурсы в папке assets вашего проекта. Чтобы получить доступ к данным ресурсам, приложение использует механизм контекста, который и отвечает доступность ресурсов для тех, кто запрашивает доступ — активность, служба и т.д. Аналогично происходит с методом getResources. Например, чтобы получить доступ к ресурсу цвета используется конструкция getResources().getColor(), которая может получить доступ к данным из файла res/colors.xml.
Таким образом, создавая, например, вторую активность, мы можем сразу обеспечить ей доступ к своим ресурсам, так как активность относится к контексту. При создании собственных компонентов View также используется контекст в конструкторах, так как компонент тоже может использовать ваши ресурсы. При создании собственных классов, если вам нужно будет обращаться к контексту, то необходимо создать конструктор:
// В классе сделайте конструктор, куда будет передаваться контекст: public MyClass(Context context) < this.context = context; >// в активности MyClass cat = new MyClass(this);
Через контекст можно узнать практически всю информацию о вашем приложении — имя пакета, класса и т.п.
// имя вашего пакета String info = this.getApplicationInfo().packageName;
Тем не менее, следует различать контекст в разных ситуациях. Допустим, у вас есть приложение с несколькими активностями. В манифесте можно прописать используемую тему как для всего приложения, так и для каждой активности в отдельности. Соответственно, выбор контекста повлияет на результат. Как правило, при использовании собственной темы предпочтительнее использовать контекст активности, а не приложения.
Очень часто начинающие программисты впадают в ступор, когда ключевое слово this не работает в анонимных классах, например, при щелчке кнопки. В этом случае, используйте полное имя класса перед ним.
Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View view) < Toast.makeText(MainActivity.this, "Мяу", Toast.LENGTH_SHORT).show(); > >);
При создании адаптеров для списков также обращаются к контексту.
if (convertView == null) < convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_user, parent, false); >
Или ещё пример для адаптера в фрагменте ListFragment:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < String[] names; // имена котов // бла-бла-бла, т.е. мяу-мяу-мяу ArrayAdapteradapter = new ArrayAdapter<>( inflater.getContext(), android.R.layout.simple_list_item_1, names); setListAdapter(adapter); return super.onCreateView(inflater, container, savedInstanceState); >
Здесь тоже следует быть внимательным, если используется своя тема для списка.
Последнее замечание относится к опытным программистам. Неправильный контекст может послужить источником утечки памяти. Если вы создадите собственный класс, в котором содержится статическая переменная, обращающая к контексту активности, то система будет держать ссылку на переменную. Если активность будет закрыта, то сборщик мусора не сможет очистить память от переменной и самой неиспользуемой активности. В таких случаях лучше использовать контекст приложения через метод getApplicationContext().
ContextCompat
В библиотеки совместимости появился свой класс для контекста ContextCompat. Он может вам пригодиться, когда студия вдруг подчеркнёт метод в старом проекте и объявит его устаревшим.
context.getResources().getColor(R.color.some_color_resource_id);
Допустим, мы хотим поменять цвет текста на кнопки.
public void onClick(View view) < int color = getResources().getColor(R.color.colorPrimary); // ругается Button button = (Button) findViewById(R.id.button); button.setTextColor(color); >
Студия ругается, что нужно использовать новый вариант getColor(int, Theme). Заменим строчку.
// Теперь не ругается int color = ContextCompat.getColor(this, R.color.colorPrimary);
Если посмотреть на исходники этого варианта, то увидим, что там тоже идёт вызов нового метода. Поэтому можно сразу использовать правильный вариант, если вы пишете под Marshmallow и выше.
// Только для API 23 и выше int color = getResources().getColor(R.color.colorPrimary, getTheme());