Что такое Context?
Кто-нибудь объясните по-человечески что такое Context в Android. Имею опыт использования, но чувствую неудовлетворенность, так как четкий его смысл ускользает. UPD. Хотелось бы узнать, исходя из вашей практики, как он меняется или не меняется в ходе работы приложения, меняется ли он от активности к активности, от активности к сервису. или он разный у каждого компонента приложения, имеет разные возможности в разных ситуациях.
Отслеживать
69.8k 9 9 золотых знаков 67 67 серебряных знаков 124 124 бронзовых знака
Чем отличается activity Context от application Context?
Activity Context создается при создании активити и уничтожается вместе с активити. Контекст – тяжелый объект. Когда говорят об утечке памяти в андроиде, имеют в виду утечку контекста, т.е. ситуацию, когда контекст активити хранится после вызова Activity.onDestroy(). Не передавайте контекст активити в другой объект, если не известно как долго этот объект проживет. Подробнее о memory leak.
Application Context – синглтон. Application Context создается при создании объекта Application и живет, пока жив процесс приложения. По этой причине Application Context можно безопасно инжектить в другие синглтоны в приложении. Не рекомендуется использовать Application Context для старта активити, потому что необходимо создание новой задачи, и для layout inflation , потому что используется дефолтная тема.
Context в Android приложении
Как следует из названия, это контекст текущего состояния приложения или объекта. Это позволяет вновь созданным объектам понять, что вообще происходит. Обычно его вызывают, чтобы получить информацию о другой части программы.
Кроме того, Context является проводником в систему, он может предоставлять ресурсы, получать доступ к базам данных, преференсам и т.д. Ещё в Android приложениях есть Activity . Это похоже на проводник в среду, в которой выполняется ваше приложение. Объект Activity наследует объект Context . Он позволяет получить доступ к конкретным ресурсам и информации о среде приложения.
Context присутствует практически повсюду в Android приложении и является самой важной его частью, поэтому необходимо понимать, как правильно его использовать.
Неправильное использование Context может легко привести к утечкам памяти в Android приложении.
Существует много разных типов контекста, поэтому давайте разберёмся, что каждый из них представляет из себя, как и когда их правильно использовать.
Контекст приложения
Это singleton-экземпляр (единственный на всё приложение), и к нему можно получить доступ через функцию getApplicationContext() . Этот контекст привязан к жизненному циклу приложения. Контекст приложения может использоваться там, где вам нужен контекст, жизненный цикл которого не связан с текущим контекстом или когда вам нужно передать контекст за пределы Activity .
Например, если вам нужно создать singleton-объект для вашего приложения, и этому объекту нужен какой-нибудь контекст, всегда используйте контекст приложения.
Если вы передадите контекст Activity в этом случае, это приведет к утечке памяти, так как singleton-объект сохранит ссылку на Activity и она не будет уничтожена сборщиком мусора, когда это потребуется.
В случае, когда вам нужно инициализировать какую-либо библиотеку в Activity , всегда передавайте контекст приложения, а не контекст Activity .
Таким образом, getApplicationContext() нужно использовать тогда, когда известно, что вам нужен контекст для чего-то, что может жить дольше, чем любой другой контекст, который есть в вашем распоряжении.
Контекст Activity
Этот контекст доступен в Activity и привязан к её жизненному циклу. Контекст Activity следует использовать, когда вы передаете контекст в рамках Activity или вам нужен контекст, жизненный цикл которого привязан к текущему контексту.
getContext() в ContentProvider
Этот контекст является контекстом приложения и может использоваться аналогично контексту приложения. К нему можно получить доступ через метод getContext() .
Когда нельзя использовать getApplicationContext()?
- Это не полноценный контекст, поддерживающий всё, что может Activity . Некоторые вещи, которые вы попытаетесь сделать с этим контекстом, потерпят неудачу, в основном связанные с графическим интерфейсом.
- Могут появляться утечки памяти, если контекст из getApplicationContext() удерживается на каком-то объекте, который вы не очищаете впоследствии. Если же где-то удерживается контекст Activity , то как только Activity уничтожается сборщиком мусора, всё остальное тоже уничтожается. Объект Application остается на всю жизнь вашего процесса.
Правило большого пальца
В большинстве случаев используйте контекст, доступный непосредственно из компонента, в котором вы работаете в данный момент. Вы можете безопасно хранить ссылку на него, если она не выходит за пределы жизненного цикла этого компонента. Как только вам нужно сохранить ссылку на контекст в объекте, который живет за пределами вашей Activity или другого компонента, даже временно, используйте ссылку на контекст приложения.
- android development
- android
- андроид
- перевод с английского
- программирование
- разработка
- devcolibri
- никто не читает теги
- Разработка мобильных приложений
- Разработка под 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());