Что такое контекст в программировании
Перейти к содержимому

Что такое контекст в программировании

  • автор:

Что такое контекст? Более обширный взгляд

Стандартные библиотеки языка очень образные и что бы понять семантику контекста надо прежде всего обратиться к самому понятию «контекст» в общепринятом понимании, а не в специфике программирования: Конте́кст (от лат. 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. контекст приложения следует использовать везде, где контекст необходимо передать за пределы жизненного цикла передающего компонента (в объекты, которые будут жить дольше, чем создавшая/вызвавшая их активность, например) во избежании удержания ссылки на этот компонент при использовании его собственного контекста и утечек памяти.
  2. во внешние библиотеки следует передавать контекст приложения по тем же причинам, что и п.1
  3. контекст приложения не имеет информации по особенностям GUI отдельной активити, если они отличаются от параметров всего приложения, в таких случаях нельзя использовать контекст приложения при работе с GUI этой активити.
  4. приложение (класс 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()); 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *