Перейти к содержимому

Context android что это

  • автор:

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

Что такое Context?

Кто-нибудь объясните по-человечески что такое Context в Android. Имею опыт использования, но чувствую неудовлетворенность, так как четкий его смысл ускользает. UPD. Хотелось бы узнать, исходя из вашей практики, как он меняется или не меняется в ходе работы приложения, меняется ли он от активности к активности, от активности к сервису. или он разный у каждого компонента приложения, имеет разные возможности в разных ситуациях.

Отслеживать

69.8k 9 9 золотых знаков 66 66 серебряных знаков 123 123 бронзовых знака

Урок 22. Intent, Intent Filter, Context — теория

На прошлом уроке (№ 21) мы создали приложение, которое содержит два Activity. Напомню, что для создания Activity, необходимо:
создать класс, с суперклассом android.app.Activity
создать Activity-запись в манифесте и указать ей созданный класс в поле Name

Надеюсь прошлый урок не вызвал особых трудностей и процедура создания Activity примерно уложилась в голове. Теперь мы можем обратить внимание на код вызова Activity.

Intent intent = new Intent(this, ActivityTwo.class); startActivity(intent);

Мы использовали объект Intent. О нем можно почитать здесь, здесь и здесь. Правда инфа достаточно сложна для понимания с нуля. Я попробую своими словами объяснить.

Что такое Intent

В нашем случае Intent – это объект, в котором мы прописываем, какое Activity нам необходимо вызвать. После чего мы передаем этот Intent-объект методу startActivity, который находит соответствующее Activity и показывает его. При создании Intent мы использовали конструктор Intent (Context packageContext, Class cls) с двумя параметрами.

Первый параметр – это Context. Если помните, когда мы программно создавали View в одном из прошлых уроков, мы тоже использовали в конструкторах объект Context. Activity является подклассом Context, поэтому мы можем использовать ее – this. Вкратце, Context – это объект, который предоставляет доступ к базовым функциям приложения таким как: доступ к ресурсам, к файловой системе, вызов Activiy и т.д. Я думаю, в дальнейшем мы рассмотрим примеры, где явно увидим, зачем Context передается и как используется.

Второй параметр – имя класса. Напомню, что при создании записи Activity в манифест-файле мы указываем имя класса. И теперь если мы укажем тот же класс в Intent – то система, просмотрев манифест-файл обнаружит соответствие и покажет соответствующий Activity.

В этом можно легко убедиться. Мы удалим запись об Activity из манифест-файла и попробуем его после этого вызвать. Откройте проект из прошлого урока P0211_TwoActivity, откройте манифест-файл, вкладка Application и удалите запись об ActivityTwo с помощью кнопки Remove. Сохраните все, запустите приложение и попробуйте вызвать Activity кнопкой “Go to Activity Two”. Приложение выдаст ошибку. Если посмотреть логи, то видим следующий текст:

ERROR/AndroidRuntime(367): android.content.ActivityNotFoundException: Unable to find explicit activity class ; have you declared this activity in your AndroidManifest.xml?

(Логи — вкладка LogCat в Eclipse. Если не видно такой, то идем в меню Window -> Show View -> Other, папка Android -> LogCat )

Система говорит нам, что не нашла такого Activity класса и любезно подсказывает, что, возможно, он не прописан в манифест-файле. Снова пропишите Activity в манифест-файле, все сохраните и запускайте. Теперь должно работать.

Явный вызов

Вызов Activity с помощью такого Intent – это явный вызов. Т.е. с помощью класса мы явно указываем какое Activity хотели бы увидеть. Это обычно используется внутри одного приложения. Схематично это можно изобразить так:

Здесь мы создаем Intent, в качестве параметра передаем ему класс Class_B. Далее вызываем метод startActivity с созданным Intent в качестве параметра. Метод проверяет AndroidManifest на наличие Activity связанной с классом Class_B и если находит, то отображает. Все это в пределах одного приложения.

Неявный вызов

Существует также неявный вызов Activity. Он отличается тем, что при создании Intent мы используем не класс, а заполняем параметры action, data, category определенными значениями. Комбинация этих значений определяют цель, которую мы хотим достичь. Например: отправка письма, открытие гиперссылки, редактирование текста, просмотр картинки, звонок по определенному номеру и т.д. В свою очередь для Activity мы прописываем Intent Filter — это набор тех же параметров: action, data, category (но значения уже свои — зависят от того, что умеет делать Activity). И если параметры нашего Intent совпадают с условиями этого фильтра, то Activity вызывается. Но при этом поиск уже идет по всем Activity всех приложений в системе. Если находится несколько, то система предоставляет вам выбор, какой именно программой вы хотите воспользоваться. Схематично это можно изобразить так:

В Application_1 создается Intent, заполняются параметры action, data, category. Для удобства, получившийся набор параметров назовем Param_C. С помощью startActivity этот Intent отправляется на поиски подходящей Activity, которая сможет выполнить то, что нам нужно (т.е. то, что определено с помощью Param_C). В системе есть разные приложения, и в каждом из них несколько Activity. Для некоторых Activity определен Intent Filter (наборы Param_A, Param_B и т.д.), для некоторых нет. Метод startActivity сверяет набор параметров Intent и наборы параметров Intent Filter для каждой Activity. Если наборы совпадают (Param_C для обоих), то Activity считается подходящей.

Если в итоге нашлась только одна Activity – она и отображается. Если же нашлось несколько подходящих Activity, то пользователю выводится список, где он может сам выбрать какое приложение ему использовать.

Например, если в системе установлено несколько музыкальных плееров, и вы запускаете mp3, то система выведет вам список Activity, которые умеют играть музыку и попросит выбрать, какое из них использовать. А те Activity, которые умеют редактить текст, показывать картинки, звонить и т.п. будут проигнорированы.

Если для Activity не задан Intent Filter (Activity_24 на схеме), то Intent с параметрами ему никак не подойдет, и оно тоже будет проигнорировано.

Если проводить аналогии — можно сравнить Intent с ключом, а Intent Filter с замкОм, за которым сидит прекрасное Activity )))

Мы будем постепенно узнавать нюансы этого механизма и значения которыми заполняются параметры action, data и category в Intent и Intent Filter. Сейчас важно понять, что в случае неявного вызова одно приложение посылает Intent, а все другие сверяют его параметры со своими Activity -> Intent Filter. Intent – это базовое понятие системы Android и без него нам никуда. Оно применяется не только для Activity. Но об этом позднее.

Ну вот, хотел написать пару вводных слов, а получилось достаточно подробное объяснение со схемами и примерами ) Надеюсь, что у меня получилось донести смысл технологии Intent-ов. В дальнейшем будем практиковаться и закрепим тему.

На следующем уроке:

— Activity LifeCycle – поведение Activity при создании, вызове, закрытии

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

Singleton vs Application Context в Android

Существует общая проблема, с которой сталкиваются разработчики Android-приложений: как правильно использовать глобальные объекты? Для этого есть два распространенных подхода: паттерн Singleton и использование Application Context.

Возьмем для примера ситуацию, когда требуется использовать объект базы данных в нескольких активностях приложения. Можно создать его как Singleton, либо поместить в Application Context и получать доступ к нему через этот контекст.

Singleton

Singleton — это паттерн проектирования, который гарантирует, что класс имеет только один экземпляр, и предоставляет глобальную точку доступа к нему. При использовании этого подхода следует помнить о синхронизации, чтобы предотвратить возможные проблемы многопоточности.

Преимущества Singleton:

  • Простота использования.
  • Позволяет легко контролировать количество экземпляров класса.

Недостатки Singleton:

  • Сложности с тестированием, так как Singleton создает глобальное состояние в приложении, что может привести к нежелательным побочным эффектам.
  • Нарушение принципа единственной ответственности, так как класс сам заботится о своем жизненном цикле.

Application Context

Application Context — это класс, предоставляющий доступ к глобальному состоянию приложения.

Преимущества Application Context:

  • Объекты, помещенные в Application Context, живут столько, сколько живет само приложение.
  • Позволяет легко передавать данные между компонентами приложения.

Недостатки Application Context:

  • Возможность утечки памяти, если неправильно использовать контекст.
  • Необходимо явно управлять жизненным циклом объектов.

В итоге, каждый из подходов имеет свои преимущества и недостатки. Выбор между ними зависит от конкретной задачи и предпочтений разработчика.

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

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