Страницы

Поиск по вопросам

Показаны сообщения с ярлыком context. Показать все сообщения
Показаны сообщения с ярлыком context. Показать все сообщения

вторник, 28 января 2020 г.

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

#android #context


Сколько уже разрабатываю приложения, до сих пор не понимаю что такое контекст. Например,
возьмем старый добрый Toast

 Toast.makeText(context, String, int);


Первый параметр статического метода makeText класса Toast - это контекст. Но я могу
передать this (если вызов метода находится не дальше одного блока кода) или MainActivity.this
(если имя класса-активности MainActivity), могу также передать getApplicationContext(). 


Так в чем разница? 
Почему в качестве контекста можно передать this? Это же ссылка на класс
Есть ли случаи когда надо передать именно getApplicationContext?
Почему контекст нужен везде, где происходит работа с интерфейсом?
Почему любой виджет имеет конструктор, в который надо передать контекст?
Что вообще такое контекст? 


Последний вопрос я задал, так как по ходу написания остальных, я понял, что ничего
о нем не знаю :)
    


Ответы

Ответ 1



класс Context содержит в себе всевозможную информацию о ресурсах системы, как уже было сказано в другом ответе. Конкретно в этом вопросе нас интересует, что он содержит, помимо прочего, и параметры темы (стилей) для отображения View Почему в качестве контекста можно передать this? Это же ссылка на класс Активити является наследником класса Context и несет в себе информацию о контексте для этой активити, поэтому мы можем использовать ссылку на именно этот класс в качестве контекста. С Fragment, к примеру, это уже не работает - он не наследуется от Context Есть ли случаи когда надо передать именно getApplicationContext? Тема (стиль) всего приложения и конкретной активити может отличаться (для активити в манифесте указан другой стиль). Тогда запрос контекста приложения и контекста активти вернет разное оформление View Почему контекст нужен везде, где происходит работа с интерфейсом? Потому что он содержит стиль для View на остальные вопросы ответ тот же - в контексте содержится информация, как должен выглядеть View. Например, стиль кнопки темы Holo и темы AppCompat сильно отличается, в контексте и содержится эта информация. Возможно в приложении могут существовать и какие то другие отличия в окружении, назначенном всему приложению и конкретной активити, тогда обращение к контексту приложения или активити тоже будет иметь значение, но мне такие отличия (кроме тем и стилей) припомнить не удалось. UPD несколько важных замечаний по getApplicationContext(), не связанных с UI приложения из этой статьи контекст приложения следует использовать везде, где контекст необходимо передать за пределы жизненного цикла передающего компонента (в объекты, которые будут жить дольше, чем создавшая/вызвавшая их активность, например) во избежании удержания ссылки на этот компонент при использовании его собственного контекста и утечек памяти. во внешние библиотеки следует передавать контекст приложения по тем же причинам, что и п.1 контекст приложения не имеет информации по особенностям GUI отдельной активити, если они отличаются от параметров всего приложения, в таких случаях нельзя использовать контекст приложения при работе с GUI этой активити. приложение (класс Application) - синглтон и его контекст тоже синглтон, этот контекст может удерживать объекты с более коротким жизненным циклом и приводить к утечкам памяти, если не позаботиться о их корректной обработке GC

Ответ 2



В исходниках класса копаться не пробовали? Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc. источник (2 ссылка запроса "context android" в Google) Если всё ещё не понятно: Context – это объект, который предоставляет доступ к базовым функциям приложения: доступ к ресурсам, к файловой системе, вызов активности и т.д. Activity является подклассом Context, поэтому в коде мы можем использовать её как ИмяАктивности.this (напр. MainActivity.this), или укороченную запись this. Классы Service, Application и др. также работают с контекстом. источник (1 ссылка запроса "context android" в Google!!!) Идеальный ответ на все Ваши вопросы.

среда, 22 января 2020 г.

Объясните смысл Context в Go

#golang #context


Здравствуйте, уже второй день пытаюсь въехать в Context, который практически везде
используется в Go. Но не могу понять, для чего именно и какой смысл в его использовании.
Статьи не помогают, походу я совсем безнадежен.
    


Ответы

Ответ 1



Контекст - это просто сборник мета-данных, ассоциированных с каким-то запросом. Простейший пример - HTTP-запросы. Контекст пришедшего в HTTP-хендлер запроса отменяется, когда разрывается TCP-соединение. Предположим, ваш HTTP-хендлер делает какую-то сложную работу в цикле. Перед хендлером стоит промежуточный слой (middleware), которая берёт находит пользователя, например по куки, и кладёт в контекст запроса. Итоговый хендлер может выглядеть так: http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() user := userFromContext(ctx) if user == nil { http.Error(w, "no user", http.StatusBadRequest) return } for i := 0; i < N; i++ { select { case <-ctx.Done(): log.Printf("request cancelled: %v", ctx.Err()) return default: } doSomethingSlow(i, user) } })

пятница, 10 января 2020 г.

Туманности и мои пробелы в знаниях с async\await и Task'ами в целом

#c_sharp #async_await #async_programming #task #context


Здравствуйте, я захотел опробовать такую вкусняшку C# как async/await и написал тестовую
программу:

class MySynchronizationContext : SynchronizationContext
{
    public override void Post(SendOrPostCallback d, object state)
    {
        Console.WriteLine("Post");
        base.Post(d, state);
    }
    public override void Send(SendOrPostCallback d, object state)
    {
        Console.WriteLine("Send");
        base.Send(d, state);
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        SynchronizationContext.SetSynchronizationContext(new MySynchronizationContext());
        var browsers = GetBrowsers();
        Console.WriteLine("start");
        Console.WriteLine(browsers.Result);
    }
    static async Task GetBrowsers()
    {
        var res = string.Empty;
        var bd = await GetFromFS();
        res += bd;               // <-тут могла быть операция с UI
        var net = await GetFromNet();
        res += " and " + net;   // <-тут могла быть операция с UI
        var cpu = await Task.Run(() => { Thread.Sleep(200); return "edge"; });
        res += " and " + cpu;   // <-тут могла быть операция с UI
        return res;
    }
    static async Task GetFromFS()
    {
        using (var sr = new StreamReader(@"C:\bd.txt"))
        {
            var res = await sr.ReadToEndAsync();
            // тут могла быть операция с UI
            return res + " and firefox";
        }
    }
    static async Task GetFromNet()
    {
        await Task.Delay(200);
        // тут могла быть операция с UI
        return "chrome";
    }

}


Я ожидал, что после каждого await'а мой контекст будет восстанавливаться (ведь будь
это приложение с UI, то надо же получать доступ к контролам), а значит, что после каждого
await'а в консоль будет выводится "Post", но каково было мое удивление когда вывелся
только 2 раза. Отсюда вопрос:


почему контекст привязывается не всегда?


Теперь к async/await: как я понимаю, начиная с var browsers = GetBrowsers(); вызов
будет проводится по стеку вниз до первого таска (в данном случае sr.ReadToEndAsync();,
а может и ниже), и управление сразу перейдет обратно в метод Main(), не дожидаясь завершения
этого таска; остальная часть async-методов будет выполняться после выполнения данного
таска и так далее, из чего возникает следующий вопрос:


кто ждет тот самый первый таск (затем следующие, когда до них дойдет
очередь после await'а), изменяет его состояние на
RanToCompletion? Думаю, было бы глупо думать, что для ожидания
выделяется поток из пула потоков, да?


Третий вопрос стоит на стыке тасков и пула потоков. Продолжение после await, как
я понимаю, выполняется в пуле потоков (там ему передается контекст), но...


что засовывает часть кода после await в пул потоков и когда (когда
таск завершился или когда создался?)?


Заранее спасибо за прояснение ситуации
    


Ответы

Ответ 1



Дело в том, что выполнение метода Post() в вашем контексте вы делегируете базовому методу. А базовый метод ставит делегат на выполнение в пуле потоков. В случае с UI такого не происходит, потому что, например, WinForms контекст полностью переопределяет методы. Вставим логирование контекста и текущего потока в ваш код: class MySynchronizationContext : SynchronizationContext { public override void Post(SendOrPostCallback d, object state) { Console.WriteLine($"Post, thread id = {Thread.CurrentThread.ManagedThreadId}"); base.Post(d, state); } public override void Send(SendOrPostCallback d, object state) { Console.WriteLine($"Send, thread id: {Thread.CurrentThread.ManagedThreadId}"); base.Send(d, state); } public override string ToString() { return "My"; } } public class Program { public static void Main(string[] args) { SynchronizationContext.SetSynchronizationContext(new MySynchronizationContext()); var browsers = GetBrowsers(); Console.WriteLine("start"); Console.WriteLine(browsers.Result); } static async Task GetBrowsers() { LogCurrentContext("GetBrowsers prologue"); var res = string.Empty; var bd = await GetFromFS(); LogCurrentContext("GetBrowsers after GetFromFS"); res += bd; // <-тут могла быть операция с UI var net = await GetFromNet(); LogCurrentContext("GetBrowsers after GetFromNet"); res += " and " + net; // <-тут могла быть операция с UI var cpu = await Task.Run(() => { Thread.Sleep(200); return "edge"; }); LogCurrentContext("GetBrowsers after Task.Run"); res += " and " + cpu; // <-тут могла быть операция с UI return res; } private static void LogCurrentContext(string message) { Console.WriteLine($"{message}: {(SynchronizationContext.Current?.ToString() ?? "default")} context, thread id = {Thread.CurrentThread.ManagedThreadId}"); } static async Task GetFromFS() { LogCurrentContext("GetFromFS prologue"); using (var sr = new StreamReader(@"D:\GetEventsMarkets.sql")) { var res = await sr.ReadToEndAsync(); LogCurrentContext("GetFromFS after ReadToEndAsync"); // тут могла быть операция с UI return res + " and firefox"; } } static async Task GetFromNet() { LogCurrentContext("GetFromNet prologue"); await Task.Delay(200); // тут могла быть операция с UI LogCurrentContext("GetFromNet after Task.Delay"); return "chrome"; } } Чаще всего я получал подобный результат: GetBrowsers prologue: My context, thread id = 1 GetFromFS prologue: My context, thread id = 1 Post, thread id = 1 GetFromFS after ReadToEndAsync: default context, thread id = 3 start Post, thread id = 3 GetBrowsers after GetFromFS: default context, thread id = 3 GetFromNet prologue: default context, thread id = 3 GetFromNet after Task.Delay: default context, thread id = 4 GetBrowsers after GetFromNet: default context, thread id = 4 GetBrowsers after Task.Run: default context, thread id = 4 Здесь нам интересны две вещи. В кастомном контексте вызываются только прологи методов GetBrowsers() и GetFromFS(). После того, как выполняется строка await sr.ReadToEndAsync(), продолжение метода GetFromFS() постится в кастомный контекст. Это первый вызов Post(). Далее метод GetFromFS() завершается и продолжение метода GetBrowsers() снова постится в кастомный контекст. Это второй вызов Post(). Однако поскольку кастомный контекст просто запускает код в пуле потоков, эти продолжения работают уже в контексте пула потоков. Именно поэтому мы больше не видим вызовов кастомного контекста. Метод GetFromFS() начал исполняться в потоке с id=1. Однако само продолжение при этом выполнялось в потоке с id=3 по причине, описанной выше. Продолжение после вызова GetFromFS() было вызвано в этом же потоке (Post, thread id = 3). "Самый первый таск", как и любой другой, ждет специальный IO поток (т.н. IO completion port, IOCP). Но такие потоки ждут очень большое количество завершений, в т.ч. и тасков, поэтому говорить о "один таск -- один ждущий поток" не приходится. Нырнуть вглубь и почитать подробнее можно в статье на Хабре. Продолжение async метода выполняется в захваченном контексте. Если такого контекста нет (например, при вызове с ConfigureAwait(false)) -- продолжение выполняется в контексте пула потоков. Вызов продолжение в соответствующем контексте выполняется компилятором -- он генерирует соответствующий код с вызовом Post(). Компилятор разбирает async метод на составляющие (пролог+продолжения) и генерирует из них стейт-машину с переходами. Очень рекомендую посмотреть это выступление (или хотя бы слайды), а также ознакомиться с этим ответом. После этого фразы вроде "async/await занимается переключением контекста" должны пропасть из вашего обихода. Как резюме: вы получили смущающие результаты потому, что ваша реализация контекста, строго говоря, некорректна. По сути она аналогична контексту пула потоков, который используется для консольных приложений и в котором исполняются все продолжения, если не был обнаружен другой контекст.

Ответ 2



почему контекст привязывается не всегда? Проблема вашего контекста - в том, что он не умеет восстанавливать себя. Если вы пишите свой контекст - то вы сами должны позаботиться чтобы все продолжения запускались в нем же. кто ждет тот самый первый таск Если асинхронность правильная - то "самый первый" Task, как и все последующие, создается при помощи механизма TaskCompletionSource. Например, так (код привожу только для примера, в реальности надо еще исключения обрабатывать): Task VeryFirstTask() { var tcs = new TaskCompletionSource(); Action handler = null; handler = () => { tcs.SetResult(42); SomeEvent -= handler; }; SomeEvent += handler; return tcs.Task; } Не обязательно используются события - но идея одна и та же. Где-то сохраняется TaskCompletionSource, у которого в нужный момент вызывается SetResult/SetException/SetCanceled. что засовывает часть кода после await в пул потоков и когда (когда таск завершился или когда создался?)? Напрямую его туда засовывает контекст синхронизации. Опосредовано в этом участвует так же такая структура данных как TaskAwaiter (она хранит захваченный контекст синхронизации).

суббота, 4 января 2020 г.

Различие между context и this

#java #android #context


В андроиде есть context-ссылка, а на самой джаве есть this-ссылка. Так вот в чем
разница контекста от зиса и можноли пример  с контекстом а то я запутался в нем. Благодарю.
    


Ответы

Ответ 1



this и Context – это принципиально разные вещи. this – это ключевое слово языка Java. this – это ссылка на самого себя. Ссылка на объект, для которого был вызван метод. Context (в android) – это абстрактный класс, предоставляющий методы для доступа к т.н. глобальной информации (к ресурсам, классам, для управления активити, сервисами и так далее). Непосредственными субклассами классами Context являются классы ContextWrapper и MockContext. В свою очередь, прямыми субклассами класса ContextWrapper, в том числе, являются классы Application и Service, а непрямым – класс Activity. Пример с Context: getActivity().runOnUiThread(new Runnable() { @Override public void run() { // some actions } }); Здесь, для запуска кода в UI-потоке используется объект класса Activity (который является (непрямым) наследником класса Context). Еще один пример с Context: LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); Здесь в конструктор класса LinearLayoutManager передается объект класса Activity. Такой вызов, возможен, например, из фрагмента. Из самой активити можно напрямую вызвать: LinearLayoutManager layoutManager = new LinearLayoutManager(this); так как this в методах активити является как раз объектом класса Activity.

понедельник, 9 декабря 2019 г.

Что такое Context?

#java #android #android_sdk #context


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

UPD. Хотелось бы узнать, исходя из вашей практики, как он меняется или не меняется
в ходе работы приложения,
 меняется ли он от активности к активности, от активности к сервису...или он разный
у каждого компонента приложения, имеет разные возможности в разных ситуациях...
    


Ответы

Ответ 1



Context - интерфейс предоставляющий глобальную информацию о среде приложения. Является абстрактным классом, реализация которого происходит с помощью Android системы. Context позволяет получить доступ к ресурсам приложения и его классам, а также осуществлять вызовы операций на уровне приложения, к примеру: Запуск Activity, Service, Broadcasting and Receiving intents, и тд. Источник Context Диаграмма:

Ответ 2



Хороший вопрос. Частенько его задают на собеседованиях на позицию Android девелопера. Наиболее краткий и верный ответ на этот вопрос может звучать примерно так: Context - это интерфейс доступа к функциям операционной системы Android. Ну и, конечно же, это не является каким-то секретом, все доступно.

суббота, 13 июля 2019 г.

Объясните смысл Context в Go

Здравствуйте, уже второй день пытаюсь въехать в Context, который практически везде используется в Go. Но не могу понять, для чего именно и какой смысл в его использовании. Статьи не помогают, походу я совсем безнадежен.


Ответ

Контекст - это просто сборник мета-данных, ассоциированных с каким-то запросом. Простейший пример - HTTP-запросы. Контекст пришедшего в HTTP-хендлер запроса отменяется, когда разрывается TCP-соединение. Предположим, ваш HTTP-хендлер делает какую-то сложную работу в цикле. Перед хендлером стоит промежуточный слой (middleware), которая берёт находит пользователя, например по куки, и кладёт в контекст запроса. Итоговый хендлер может выглядеть так:
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() user := userFromContext(ctx) if user == nil { http.Error(w, "no user", http.StatusBadRequest) return }
for i := 0; i < N; i++ { select { case <-ctx.Done(): log.Printf("request cancelled: %v", ctx.Err()) return default: }
doSomethingSlow(i, user) } })

четверг, 28 марта 2019 г.

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

Сколько уже разрабатываю приложения, до сих пор не понимаю что такое контекст. Например, возьмем старый добрый Toast
Toast.makeText(context, String, int);
Первый параметр статического метода makeText класса Toast - это контекст. Но я могу передать this (если вызов метода находится не дальше одного блока кода) или MainActivity.this (если имя класса-активности MainActivity), могу также передать getApplicationContext().
Так в чем разница? Почему в качестве контекста можно передать this? Это же ссылка на класс Есть ли случаи когда надо передать именно getApplicationContext? Почему контекст нужен везде, где происходит работа с интерфейсом? Почему любой виджет имеет конструктор, в который надо передать контекст? Что вообще такое контекст?
Последний вопрос я задал, так как по ходу написания остальных, я понял, что ничего о нем не знаю :)


Ответ

класс Context содержит в себе всевозможную информацию о ресурсах системы, как уже было сказано в другом ответе. Конкретно в этом вопросе нас интересует, что он содержит, помимо прочего, и параметры темы (стилей) для отображения View
Почему в качестве контекста можно передать this? Это же ссылка на класс
Активити является наследником класса Context и несет в себе информацию о контексте для этой активити, поэтому мы можем использовать ссылку на именно этот класс в качестве контекста. С Fragment, к примеру, это уже не работает - он не наследуется от Context
Есть ли случаи когда надо передать именно getApplicationContext?
Тема (стиль) всего приложения и конкретной активити может отличаться (для активити в манифесте указан другой стиль). Тогда запрос контекста приложения и контекста активти вернет разное оформление View
Почему контекст нужен везде, где происходит работа с интерфейсом?
Потому что он содержит стиль для View
на остальные вопросы ответ тот же - в контексте содержится информация, как должен выглядеть View. Например, стиль кнопки темы Holo и темы AppCompat сильно отличается, в контексте и содержится эта информация.
Возможно в приложении могут существовать и какие то другие отличия в окружении, назначенном всему приложению и конкретной активити, тогда обращение к контексту приложения или активити тоже будет иметь значение, но мне такие отличия (кроме тем и стилей) припомнить не удалось.
UPD несколько важных замечаний по getApplicationContext(), не связанных с UI приложения из этой статьи
контекст приложения следует использовать везде, где контекст необходимо передать за пределы жизненного цикла передающего компонента (в объекты, которые будут жить дольше, чем создавшая/вызвавшая их активность, например) во избежании удержания ссылки на этот компонент при использовании его собственного контекста и утечек памяти. во внешние библиотеки следует передавать контекст приложения по тем же причинам, что и п.1 контекст приложения не имеет информации по особенностям GUI отдельной активити, если они отличаются от параметров всего приложения, в таких случаях нельзя использовать контекст приложения при работе с GUI этой активити. приложение (класс Application) - синглтон и его контекст тоже синглтон, этот контекст может удерживать объекты с более коротким жизненным циклом и приводить к утечкам памяти, если не позаботиться о их корректной обработке GC

вторник, 29 января 2019 г.

Различие между context и this

В андроиде есть context-ссылка, а на самой джаве есть this-ссылка. Так вот в чем разница контекста от зиса и можноли пример с контекстом а то я запутался в нем. Благодарю.


Ответ

this и Context – это принципиально разные вещи.
this – это ключевое слово языка Java. this – это ссылка на самого себя. Ссылка на объект, для которого был вызван метод.
Context (в android) – это абстрактный класс, предоставляющий методы для доступа к т.н. глобальной информации (к ресурсам, классам, для управления активити, сервисами и так далее).
Непосредственными субклассами классами Context являются классы ContextWrapper и MockContext. В свою очередь, прямыми субклассами класса ContextWrapper, в том числе, являются классы Application и Service, а непрямым – класс Activity
Пример с Context
getActivity().runOnUiThread(new Runnable() { @Override public void run() { // some actions } });
Здесь, для запуска кода в UI-потоке используется объект класса Activity (который является (непрямым) наследником класса Context).
Еще один пример с Context
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
Здесь в конструктор класса LinearLayoutManager передается объект класса Activity. Такой вызов, возможен, например, из фрагмента.
Из самой активити можно напрямую вызвать:
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
так как this в методах активити является как раз объектом класса Activity

пятница, 12 октября 2018 г.

Что такое Context?

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


Ответ

Context - интерфейс предоставляющий глобальную информацию о среде приложения. Является абстрактным классом, реализация которого происходит с помощью Android системы. Context позволяет получить доступ к ресурсам приложения и его классам, а также осуществлять вызовы операций на уровне приложения, к примеру: Запуск Activity, Service, Broadcasting and Receiving intents, и тд.
Источник Context
Диаграмма: