Класс context android kotlin

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 также используется контекст в конструкторах, так как компонент тоже может использовать ваши ресурсы. При создании собственных классов, если вам нужно будет обращаться к контексту, то необходимо создать конструктор:

Через контекст можно узнать практически всю информацию о вашем приложении — имя пакета, класса и т.п.

Тем не менее, следует различать контекст в разных ситуациях. Допустим, у вас есть приложение с несколькими активностями. В манифесте можно прописать используемую тему как для всего приложения, так и для каждой активности в отдельности. Соответственно, выбор контекста повлияет на результат. Как правило, при использовании собственной темы предпочтительнее использовать контекст активности, а не приложения.

Очень часто начинающие программисты впадают в ступор, когда ключевое слово this не работает в анонимных классах, например, при щелчке кнопки. В этом случае, используйте полное имя класса перед ним.

При создании адаптеров для списков также обращаются к контексту.

Или ещё пример для адаптера в фрагменте ListFragment:

Здесь тоже следует быть внимательным, если используется своя тема для списка.

Последнее замечание относится к опытным программистам. Неправильный контекст может послужить источником утечки памяти. Если вы создадите собственный класс, в котором содержится статическая переменная, обращающая к контексту активности, то система будет держать ссылку на переменную. Если активность будет закрыта, то сборщик мусора не сможет очистить память от переменной и самой неиспользуемой активности. В таких случаях лучше использовать контекст приложения через метод getApplicationContext().

ContextCompat

В библиотеки совместимости появился свой класс для контекста ContextCompat. Он может вам пригодиться, когда студия вдруг подчеркнёт метод в старом проекте и объявит его устаревшим.

Допустим, мы хотим поменять цвет текста на кнопки.

Студия ругается, что нужно использовать новый вариант getColor(int, Theme). Заменим строчку.

Если посмотреть на исходники этого варианта, то увидим, что там тоже идёт вызов нового метода. Поэтому можно сразу использовать правильный вариант, если вы пишете под Marshmallow и выше.

Источник

Context — контекст в android — что это, как получить и зачем использовать

Контекст (Context) – это базовый абстрактный класс, реализация которого обеспечивается системой Android. Этот класс имеет методы для доступа к специфичным для конкретного приложения ресурсам и классам и служит для выполнения операций на уровне приложения, таких, как запуск активностей, отправка широковещательных сообщений, получение намерений и прочее. От класса Context наследуются такие крупные и важные классы, как Application, Activity и Service, поэтому все его методы доступны из этих классов.


Получить контекст внутри кода можно одним из следующих методов:

  • getBaseContext(получить ссылку на базовый контекст)
  • getApplicationContext(получить ссылку на объект приложения)
  • getContext (внутри активности или сервиса получить ссылку на этот объект)
  • this(то же, что и getContext)
  • MainActivity.this (внутри вложенного класса или метода получить ссылку на объект MainActivity)
  • getActivity(внутри фрагмента получить ссылку на объект родительской активности)

Контекст (Context) – это базовый абстрактный класс, реализация которого обеспечивается системой Android. Этот класс имеет методы для доступа к специфичным для конкретного приложения ресурсам и классам и служит для выполнения операций на уровне приложения, таких, как запуск активностей, отправка широковещательных сообщений, получение намерений и прочее. От класса Context наследуются такие крупные и важные классы, как Application, Activity и Service, поэтому все его методы доступны из этих классов. Источник


Получить контекст внутри кода можно одним из следующих методов:

  • getBaseContext(получить ссылку на базовый контекст)
  • getApplicationContext(получить ссылку на объект приложения)
  • и(внутри активности или сервиса получить ссылку на этот объект)
  • this(то же, что и getContext)
  • MainActivity.this (внутри вложенного класса или метода получить ссылку на объект MainActivity)
  • getActivity(внутри фрагмента получить ссылку на объект родительской активности)
Читайте также:  Смс ios для android

Сообщение умрёт вместе с приложением:
Toast.makeText(getApplicationContext(), «Text «, Toast.LENGTH_SHORT).show();

Будет видно даже после завершения приложения:
Toast.makeText(getBaseContext(), «Text «, Toast.LENGTH_SHORT).show();

Здравствуйте! В статье ошибка, в списке методов получения контекста вместо getContextи
Большое спасибо за уроки!

Добрый день. Я наверное не совсем до конца понимаю, но при использовании Toast.makeText(this, «Text», Toast.LENGTH_SHORT).show(); сообщение не умирает вместе в активностью. Я в onCreate поместил вот такой код:
Toast.makeText(this, «This is toast», Toast.LENGTH_LONG).show();
finish();
и при запуске активити сразу же умирает, а Toast остается видным. Объясните что я делаю не так?

Метод finish() завершает активити, а не тост.

Для отправки комментария вам необходимо авторизоваться.

Источник

Different ways to get Context in Android

Context is one of the important and most used property. You need Context to perform a lot of things on Android. Be is displaying a toast or Accessing database, you use context a lot while building Android app.

Context is property, well, which can give you the context of whats happening on the Screen/Activity it belongs to. It contains information about what Views are there, How they are laid out etc.

So, it is important to know different types of Context and methods you can call to get context. Lets get started.

The “this” Keyword

The this keyword in general sense refers to current class instance. So, when use “this” keyword inside an Activity, it refers to that Activity instance. And as Activity is subclass of “Context”, you will get context of that activity.

If you are not directly inside Activity, for example inside an OnClickListener, you can get the current context by referencing with Activity name like MainActivity.this (Java) or this@MainActivity (Kotlin)

Get current activity context : View.getContext()

This method can be called on a View like textView.getContext() . This will give the context of activity in which the view is currently hosted in.

Get App-level context : getApplicationContext()

If you need to access resources which are out of scope of specific activity, like when accessing SharedPreferences, displaying Toast message etc. you can use this.

So unlike activity context, which will be destroyed when close an activity, Application Context the application wide context which won’t get destroyed until you completely close application.

You can directly access application context by calling getApplicationContext() or by calling on activity context like context.getApplicationContext()

Get Original context : getBaseContext()

This method is only useful when you are using ContextWrapper. You can get the original context which was wrapped by ContextWrapper by calling contextWrapper.getBaseContext()

( ContextWrapper is a wrapper class, using which you can override any method of Context, while still retaining the original context)

Get Context from Fragment : getContext()

When you call getContext() from an Fragment, you will get the context of the activity in which that fragment is hosted in.

Get parent Activity : getActivity()

You can get the parent activity from a Fragment by calling getActivity() .

💡Difference : Both getContext() and getActivity() are not much different in most cases, when you just need a context as both will get Parent activity context. Except for some cases, for example when using ContextWrapper, getContext() and getActivity() can point to different contexts.

Non-nullable Context : requireContext() and requireActivity()

These methods are same but “NotNull” versions of getContext() and getActivity() respectively. Usually, if a fragment is detached from Activity, you will get “null” value when you call getContext() or getActivity() . So even when you are sure the context won’t be null, you still have to add null checks (especially in Kotlin) because they return Nullable type.

But requireContext() and requireActivity() will throw IllegalStateException instead of returning null, if there is no context.

These methods are mainly useful when you using Kotlin and you need a Non-Nullable Context. So using these methods instead, is matter of personal preference.

So, did you learn something new? If you did, please clap and share the post. 😄

Источник

Введение в контекстно-ориентированное программирование на Kotlin

В этой статье я постараюсь описать новое явление, которое возникло как побочный результат стремительного развития языка Kotlin. Речь идет о новом подходе к проектированию архитектуры приложений и библиотек, который я буду называть контекстно-ориентированным программированием.

Несколько слов о разрешении функций

Как хорошо известно, существует три основных парадигмы программирования (примечание Педанта: есть и другие парадигмы):

  • Процедурное программирование
  • Объектно-ориентированное программирование
  • Функциональное программирование
Читайте также:  Android system webview не скачивается

Все эти подходы так или иначе работают с функциями. Давайте посмотрим на это с точки зрения разрешения функций, или диспетчеризации их вызовов (имеется в виду выбор функции, которая должна быть использована в данном месте). Для процедурного программирования характерно использование глобальных функций и их статическое разрешение, основанное на имени функции и типах аргументов. Конечно, типы могут быть использованы только в случае статически типизированных языков. Например, в Python функции вызываются по имени, и если аргументы неправильные, в конце концов возбуждается исключение в рантайме во время выполнения программы. Разрешение функций в языках с процедурным подходом основано только на имени процедуры/функции и ее параметрах, и в большинстве случаев делается статически.

Объектно-ориентированный стиль программирования ограничивает области видимости функций. Функции не глобальны, вместо этого они являются частью классов, и могут быть вызваны только для экземпляра соответствующего класса (примечание Педанта: некоторые классические процедурные языки имеют модульную систему и, значит, области видимости; процедурный язык != С).

Конечно, мы всегда можем заменить функцию-члена класса глобальной функцией с дополнительным аргументом, имеющим тип вызываемого объекта, но с синтаксической точки зрения разница довольно значительна. Например, в этом случае методы сгруппированы в классе, к которому они обращаются, и поэтому более ясно видно какое поведение обеспечивают объекты данного типа.

Конечно, наиболее важны здесь инкапсуляция, благодаря которой некоторые поля класса или его поведение могут быть приватными и доступными только членам этого класса (вы не можете обеспечить этого в чисто процедурном подходе), и полиморфизм, благодаря которому фактически используемый метод определяется не только на основе имени метода, но и на основе типа объекта, из которого он вызывается. Диспетчеризация вызова метода в объектно-ориентированном подходе зависит от типа объекта, определяемого в рантайме, имени метода, и типа аргументов на этапе компиляции.

Функциональный подход не приносит чего-то принципиально нового в плане разрешения функций. Обычно функционально-ориентированные языки имеют лучшие правила для разграничения областей видимости (примечание педанта: еще раз, C — это еще не все процедурные языки, есть такие, в которых области видимости хорошо разграничены), которые позволяют проводить более скрупулезный контроль видимости функций на основе системы модулей, но кроме этого, разрешение проводится во время компиляции основываясь на типе аргументов.

Что такое this?

В случае объектного подхода, при вызове метода у объекта, у нас есть его аргументы, но кроме того мы имеем явный (в случае Python) или неявный параметр, представляющий экземпляр вызываемого класса (здесь и далее все примеры написаны на Kotlin):

Вложенные классы и замыкания все несколько усложняют:

В данном случае есть два неявных this для функции doBSomething — один соответствует экземпляру класса B, а другой возникает от замыкания экземпляра A. То же самое происходит в намного более часто встречающемся случае лямбда-замыкания. Важно отметить, что this в данном случае работает не только как неявный параметр, но и как область или контекст для всех функций и объектов, вызываемых в лексической области определения. Так что метод doBSomething на самом деле имеет доступ к любым, открытым или закрытым, членам класса A, так же как и к членам самого B.

А вот и Kotlin

Kotlin дает нам совершенно новую «игрушку» – функции-расширения. (Примечание Педанта: на самом деле не такие уж новые, в C# они тоже есть). Вы можете определить функцию вроде A.doASomething() где угодно в программе, не только внутри A. Внутри этой функции у нас есть неявный this-параметр, называемый получателем (receiver), указывающий на экземпляр A на котором метод вызывается:

У функций-расширений нет доступа к закрытым членам их получателя, так что инкапсуляция не нарушается.

Следующая важная вещь, которая есть в Kotlin — блоки кода с получателями. Можно запустить произвольный блок кода используя что-нибудь в качестве получателя:

В этом примере обе функции можно было вызвать без дополнительного «a.» в начале, потому что функция with помещает весь код последующего блока внутрь контекста a. Это значит, что все функции в этом блоке вызываются так, как если бы они вызывались на (явно переданном) объекте a.

Окончательный на этот момент шаг к контекстно-ориентированному программированию — возможность объявлять расширения как члены класса. В этом случае функция-расширение определяется внутри другого класса, вот так:

Важно, что здесь B получает некоторое новое поведение, но только когда находится в конкретном лексическом контексте. Функция-расширение является обычным членом класса A. Это значит, что разрешение функции делается статически на основе контекста, в котором она вызывается, но настоящая реализация определяется экземпляром A, передаваемым в качестве контекста. Функция может даже взаимодействовать с состоянием объекта a.

Контекстно-ориентированная диспетчеризация

В начале статьи мы обсудили разные подходы к диспетчеризации вызовов функций, и это было сделано не просто так. Дело в том, что функции-расширения в Kotlin позволяют работать с диспетчеризацией по-новому. Теперь решение о том, какая конкретно функция должна быть использована, основано не только на типе ее параметров, но и на лексическом контексте ее вызова. То есть то же самое выражение в разных контекстах может иметь разное значение. Конечно, с точки зрения реализации ничего не меняется, и у нас по-прежнему есть явный объект-получатель, который определяет диспетчеризацию для своих методов и расширений, описанных в теле самого класса (member extensions) — но с точки зрения синтаксиса, это другой подход.

Читайте также:  Рейтинг фермы для андроид рейтинг

Давайте рассмотрим, как контекстно-ориентированный подход отличается от классического объектно-ориентированного, на примере классической проблемы арифметических операций над числами в Java. Класс Number в Java и Kotlin является родительским для всех чисел, но в отличие от специализированных чисел вроде Double, он не определяет своих математических операций. Так что нельзя писать, например, так:

Причина здесь в том, что невозможно согласованно определить арифметические операции для всех числовых типов. К примеру, деление целых чисел отличается от деления чисел с плавающей точкой. В некоторых особых случаях пользователь знает, какой тип операций нужен, но обычно нет смысла определять такие вещи глобально. Объектно-ориентированным (и, на самом деле, функциональным) решением было бы определить новый тип-наследник класса Number, нужные операции в нем, и использовать его где необходимо (в Kotlin 1.3 можно использовать встраиваемые (inline) классы). Вместо этого, давайте определим контекст с этими операциями и применим его локально:

В этом примере расчет res делается внутри контекста, который определяет дополнительные операции. Контекст не обязательно определять локально, вместо этого он может быть передан неявно как получатель функции. Например, можно сделать так:

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

Также стоит помнить, что контексты могут быть вложенными:

Это дает эффект комбинирования поведений обоих классов, однако данную фичу на сегодняшний день трудно контролировать из-за отсутствия расширений с множественными получателями (KT-10468).

Мощь явных корутин (coroutines)

Один из лучших примеров контекстно-ориентированного подхода использован в библиотеке Kotlinx-coroutines. Объяснение идеи можно найти в статье Романа Елизарова. Здесь я только хочу подчеркнуть, что CoroutineScope — это случай контекстно-ориентированного дизайна с контекстом, имеющим состояние. CoroutineScope играет две роли:

  • Он содержит CoroutineContext, который нужен для запуска корутин и наследуется когда запускается новая сопрограмма.
  • Он содержит состояние родительской корутины, позволяющее отменить ее в случае, если порожденная сопрограмма выкидывает ошибку.

Также, структурированная конкурентность (structured concurrency) предоставляет отличный пример контекстно-ориентированной архитектуры:

Здесь doSomeWork — это контекстная функция, но определенная за пределами ее контекста. Методы launch создают два вложенных контекста, которые эквивалентны лексическим областям соответствующих функций (в данном случае оба контекста имеют один и тот же тип, поэтому внутренний контекст затеняет внешний). Хорошей отправной точкой для изучения сопрограмм в Kotlin является официальное руководство.

Существует широкий класс задач для Kotlin, на которые обычно ссылаются как на задачи построения DSL (Domain Specific Language). Под DSL при этом понимается некоторый код, обеспечивающий дружественный пользователю построитель (builder) какой-то сложной внутри структуры. На самом деле использование термина DSL здесь не совсем корректно, т.к. в таких случаях просто используется базовый синтаксис Kotlin без каких-либо специальных ухищрений — но давайте все-таки использовать этот распространенный термин.

DSL-построители в большинстве случаев контекстно ориентированы. Например, если вы хотите создать HTML-элемент, надо в первую очередь проверить, можно ли добавлять этот конкретный элемент в данное место. Библиотека kotlinx.html достигает этого предоставлением основанных на контексте расширений классов, представляющих определенный тег. По сути, вся библиотека состоит из контекстных расширений для существующих элементов DOM.

Другой пример — построитель GUI TornadoFX. Весь построитель графа сцены устроен как последовательность вложенных контекст-построителей, где внутренние блоки отвечают за построение детей для внешних блоков или подстройку параметров родителей. Вот пример из официальной документации:

В этом примере лексическая область определяет свой контекст (что логично, т.к. он представляет раздел GUI и его внутреннее устройство), и имеет доступ к родительским контекстам.

Что дальше: множественные получатели

Контекстно-ориентированное программирование дает разработчикам Kotlin множество инструментов и открывает новый способ дизайна архитектуры приложений. Нужно ли нам что-то еще? Вероятно, да.

На данный момент разработка в контекстном подходе ограничена тем фактом, что нужно определять расширения, чтобы получить какое-то ограниченное контекстом поведение класса. Это нормально, когда речь идет о пользовательском классе, но что если мы хотим то же самое для класса из библиотеки? Или если мы хотим создать расширение для уже ограниченного в области поведения (например, добавить какое-то расширение внутрь CoroutineScope)? На данный момент Kotlin не позволяет функциям-расширениям иметь более одного получателя. Но множественные получатели можно было бы добавить в язык, не нарушая обратной совместимости. Возможность использования множественных получателей сейчас обсуждается (KT-10468) и будет оформлена в виде KEEP-запроса (UPD: уже оформлена). Проблема (или, может быть, фишка) вложенных контекстов — в том, что они позволяют покрыть большинство, если не все, варианты использования классов типов (type-classes), другой очень желанной из предложенных фич. Довольно маловероятно, что обе эти фичи будут реализованы в языке одновременно.

Дополнение

Хотим поблагодарить нашего штатного Педанта и любителя Haskell Алексея Худякова за его замечания по тексту статьи и поправки по моему достаточно вольному использованию терминов. Также благодарю Илью Рыженкова за ценные замечания и вычитку английской версии статьи.

Источник

Оцените статью