DEV_EASY_NOTES Telegram 145
Итак, задумывались ли вы, что происходит когда вы достаете из Context скажем ConnectivityManager? Как вы помните ConnectivityManager это класс, который позволяет отлеживать состояние сети. У него достаточно удобное API позволяющее узнать если ли сейчас сеть, повесить колбеки на это, короче все что связано с сетью. Получаем мы его вот так:

val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

И вот если вдуматься в синтаксис, ну абсурд же происходит! Вроде достаем сервис, а получаем менеджер. Да и системный же сервис работает в другом процессе, что за дичь вообще? Сейчас все раскидаем. Наше приключение начинается с Context. Два основных факта про Context. Первый – Context это God object умеющий все на свете и вообще связующий класс через который мы общаемся с системой. Второй – сам по себе Context это абстрактный класс.

У Context куча наследников, в том числе основные компоненты: Application, Activity, Service и т.д. В Context 200 методов и реализовывать их в каждом наследнике, учитывая то, что они делают примерно одно и тоже, это сизифов труд. Поэтому разработчики сделали класс ContextImpl, который реализует основные методы. Вспоминаем шаблон декоратор. Activity наследует Context, после Activity переопределяет методы Context которые ей нужны, а все остальные методы просто вызывают методы класса ContextImpl. Аналогично и во всеми остальными наследниками Context.

Нас сейчас интересует конкретный метод Context getSystemService. Каждый раз при вызове этого метода он идет в SystemServiceRegistry, который по сути: Map<String, (Context) -> Any>. И getSystemService делает примерно вот что:

fun getSystemService(str:Stiring): Any {
val fetcher = systemServiceRegistry[str]
return fetcher(this)
}


SystemServiceRegistry это класс, в котором огромный блок static наполняющий эту саму Map. Суть – есть имя сервиса и логика как его получить, обращаемся к SystemServiceRegistry по имени сервиса, и он нам его собирает. Точнее говоря, собирает не сам сервис, а некоторого клиента или менеджера который умеет работать с каким-то системным сервисом. Именно так мы и получаем ConnectivityManager, однако это только начало.

При старте системы, она запускает SystemServer, который в свою очередь запускает системные сервисы, прям все. Сервисов много, но нас сейчас интересует ConnectivityServiceInitializer. ConnectivityServiceInitializer это системный сервис, основная задача которого просто создать объект класса ConnectivityService и сохранить его у себя. Хоть ConnectivityService и называется сервисом, это просто обычный класс, в котором скрыта логика по общению с netd. С тем самым демоном о котором говорили ранее.

Если ты дочитал до сюда и все еще легко ставь❤️. В системе есть AIDL интерфейс с названием IConnectivityManager. ConnectivityService это Stub интерфейса IConnectivityManager. Или по другому, к ConnectivityService кто-то может стучаться через Binder и вызывать его методы из другого процесса. И этот кто-то ConnectivityManager, который при создании получает Proxy интерфейса IConnectivityManager. Получив proxy, можно вызывать методы ConnectivityManager, который крутится в ConnectivityServiceInitializer и имеющий доступ к netd, а тем самым к информации о сети.

Жестко, я понимаю сам офигивал от такой картины. Главное тут это то, что во многих аспектах работает связка Manager–Service. Складываем все части мозаики воедино получаем что, есть системные сервисы и есть всякие менеджеры которые мы получаем из Context. Через эти менеджеры мы можем общаться с системными сервисами и общение это происходит через Binder. Разумеется не все что мы получаем через getSystemService обязательно общается с каким-то системным сервисом. Есть например LayoutInflator который ни с кем не общается и просто создается как обычный объект в SystemServiceRegistry.

В этом посте описана суть на примере ConnectivityManager. Есть некоторые сервисы, которые построены сложнее, где по 10 слоев абстракций между менеджером и системным сервисом. Однако основа у всех одна.
59👍9🤯4🔥2



tgoop.com/dev_easy_notes/145
Create:
Last Update:

Итак, задумывались ли вы, что происходит когда вы достаете из Context скажем ConnectivityManager? Как вы помните ConnectivityManager это класс, который позволяет отлеживать состояние сети. У него достаточно удобное API позволяющее узнать если ли сейчас сеть, повесить колбеки на это, короче все что связано с сетью. Получаем мы его вот так:

val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

И вот если вдуматься в синтаксис, ну абсурд же происходит! Вроде достаем сервис, а получаем менеджер. Да и системный же сервис работает в другом процессе, что за дичь вообще? Сейчас все раскидаем. Наше приключение начинается с Context. Два основных факта про Context. Первый – Context это God object умеющий все на свете и вообще связующий класс через который мы общаемся с системой. Второй – сам по себе Context это абстрактный класс.

У Context куча наследников, в том числе основные компоненты: Application, Activity, Service и т.д. В Context 200 методов и реализовывать их в каждом наследнике, учитывая то, что они делают примерно одно и тоже, это сизифов труд. Поэтому разработчики сделали класс ContextImpl, который реализует основные методы. Вспоминаем шаблон декоратор. Activity наследует Context, после Activity переопределяет методы Context которые ей нужны, а все остальные методы просто вызывают методы класса ContextImpl. Аналогично и во всеми остальными наследниками Context.

Нас сейчас интересует конкретный метод Context getSystemService. Каждый раз при вызове этого метода он идет в SystemServiceRegistry, который по сути: Map<String, (Context) -> Any>. И getSystemService делает примерно вот что:

fun getSystemService(str:Stiring): Any {
val fetcher = systemServiceRegistry[str]
return fetcher(this)
}


SystemServiceRegistry это класс, в котором огромный блок static наполняющий эту саму Map. Суть – есть имя сервиса и логика как его получить, обращаемся к SystemServiceRegistry по имени сервиса, и он нам его собирает. Точнее говоря, собирает не сам сервис, а некоторого клиента или менеджера который умеет работать с каким-то системным сервисом. Именно так мы и получаем ConnectivityManager, однако это только начало.

При старте системы, она запускает SystemServer, который в свою очередь запускает системные сервисы, прям все. Сервисов много, но нас сейчас интересует ConnectivityServiceInitializer. ConnectivityServiceInitializer это системный сервис, основная задача которого просто создать объект класса ConnectivityService и сохранить его у себя. Хоть ConnectivityService и называется сервисом, это просто обычный класс, в котором скрыта логика по общению с netd. С тем самым демоном о котором говорили ранее.

Если ты дочитал до сюда и все еще легко ставь❤️. В системе есть AIDL интерфейс с названием IConnectivityManager. ConnectivityService это Stub интерфейса IConnectivityManager. Или по другому, к ConnectivityService кто-то может стучаться через Binder и вызывать его методы из другого процесса. И этот кто-то ConnectivityManager, который при создании получает Proxy интерфейса IConnectivityManager. Получив proxy, можно вызывать методы ConnectivityManager, который крутится в ConnectivityServiceInitializer и имеющий доступ к netd, а тем самым к информации о сети.

Жестко, я понимаю сам офигивал от такой картины. Главное тут это то, что во многих аспектах работает связка Manager–Service. Складываем все части мозаики воедино получаем что, есть системные сервисы и есть всякие менеджеры которые мы получаем из Context. Через эти менеджеры мы можем общаться с системными сервисами и общение это происходит через Binder. Разумеется не все что мы получаем через getSystemService обязательно общается с каким-то системным сервисом. Есть например LayoutInflator который ни с кем не общается и просто создается как обычный объект в SystemServiceRegistry.

В этом посте описана суть на примере ConnectivityManager. Есть некоторые сервисы, которые построены сложнее, где по 10 слоев абстракций между менеджером и системным сервисом. Однако основа у всех одна.

BY Dev Easy Notes


Share with your friend now:
tgoop.com/dev_easy_notes/145

View MORE
Open in Telegram


Telegram News

Date: |

The initiatives announced by Perekopsky include monitoring the content in groups. According to the executive, posts identified as lacking context or as containing false information will be flagged as a potential source of disinformation. The content is then forwarded to Telegram's fact-checking channels for analysis and subsequent publication of verified information. With Bitcoin down 30% in the past week, some crypto traders have taken to Telegram to “voice” their feelings. bank east asia october 20 kowloon To upload a logo, click the Menu icon and select “Manage Channel.” In a new window, hit the Camera icon. Clear
from us


Telegram Dev Easy Notes
FROM American