2. Исходный текст компилируется в промежуточный низкоуровневый язык MSIL. При этом формируется пакет, состоящий из некоторого числа сборок, одна из которых является исполняемой и содержит точку входа в программу. В других — содержатся библиотечные файлы. Сборки содержат метаданные и код на промежуточном языке.
Метаданные включают в себя информацию о типах данных, методах сборки и ХЭШ. ХЭШ содержит информацию о версиях и привилегиях, а так же какие другие сборки будут вызываться этой сборкой.
3. Среда CLR загружает сборку, содержащую точку входа в программу и анализирует ХЭШ для проверки целостности сборки и требуемых привилегиях. При этом происходит обращение к политике безопасности системы и учетной записи пользователя. Если пользователь обладает требуемыми привилегиями, то они будут предоставлены программе.
CLR осуществляет так же проверку безопасности кода по типу памяти. Т.е. исполняемый код не должен пытаться читать или записывать в область памяти не принадлежащей ему. Если данное требование нарушается, то приложение снимается с выполнения.
LPIC 101.2 Процесс загрузки Linux
4. CLR компилирует с помощью компилятора JIT (Just-in-time) программу на промежуточном языке MSIL в машинный код и запускает ее на выполнение. Причем компилируется только та часть программы, выполнение которой требуется в данный момент времени. Скомпилированный код сохраняется в ОЗУ ЭВМ и при повторном обращении к нему, перекомпиляции не происходит, а, следовательно, не происходи потери производительности, свойственных, например, компилятору-интерпретатору.
5. Во время выполнения кода периодически запускается так называемый сборщик мусора, который на основе анализа данных освобождает области памяти из-под объектов, которые больше не используются.
Историческая справка.
Язык программирования С — был разработан в 1972 г. Денисом Ричи в компании Bell Laboratories. Язык С — является первым структурным языком программирования.
В конце 1970 начале 1980 годов многие проекты достигли размера свыше пяти тысяч строк кода. Эта величина оценивается как предельная для языка структурного программирования. Свыше данного размера возникают большие трудности для понимания и сопровождения программ. Эта проблема была решена с помощью нового в то время подхода – объектно-ориентированного программирования (ООП).
В 1979 году Бьярном Страуструпом был разработан, на основе языка С, объектно-ориентированный язык – С с классами, который в последствии был переименован в 1983 в С++.
Долгое время язык оставался в тени. Первое справочное руководство по этому языку было выпущено только в 1991 году:
— Stroustroup, 1991.»The C++ Programming Language».
И с этого момента он начинает широко применяться и приобретает большую популярность.
Следующим шагом в развитии языков программирования явилось появление языка программирования Java.
Работа над проектом Java, который первоначально назывался Oak, началась в 1991 году. Он создавался как независящий от платформы язык, предназначенный для разработки программного обеспечения (ПО) для контроллеров, встроенных в различные устройства (пылесосы, стиральные машины и т.п.).
Процесс загрузки Linux. Systemd, Kernel, GRUB2, Bios
В связи с бурным развитием сети Internet, которая объединяла компьютеры, реализованные на различных платформах, возникла проблема переносимости ПО с одной платформы на другую. В 1993 году для разработчиков Java стало очевидным, что идеи платформенной независимости языка легко переносятся с уровня встроенных контроллеров на уровень Internet.
Идея платформенной независимости Java заключается в том, что исходный текст программы транслируется в некоторый промежуточный язык, называемый байт-кодом. Каждый байт-код соответствует одной машинной инструкции некоторого абстрактного микропроцессора. Набор инструкций абстрактного микропроцессора соответствует набору инструкций, поддерживаемого большинством реальных микропроцессоров. Байт-код не зависит от платформы и может быть переслан по сети Internet для выполнения на любом типе компьютера, на котором установлена, так называемая, виртуальная машина Java (Java Virtual Machine — JVM).
Виртуальная машина Java работает в режиме интерпретатора и, в настоящее время, реализована для большинства платформ. Благодаря тому, что соответствие байт-кода инструкциям машинного кода реального процессора, составляют почти один к одному процесс трансляции и выполнение программы на байт коде происходит с приемлемой скоростью.
Язык программирования Java был создан на основе языка С и С++ (синтаксис его очень сходен с синтаксисом С++ и С) и является структурным объектно-ориентированным языком.
Следующим шагом в развитии языков программирования явилась разработка под руководством Андерсена Хейльсберга в конце 90-х годов языка C #. Первая альфа-версия этого языка была выпущена в середине 2000 года. C# является прямым наследником С++. Многие синтаксические конструкции и ключевые слова он унаследовал от языка С++.
Отличительной особенностью языка программирования C# является то, что он, как и Java компилируется в промежуточный язык (Microsoft Intermediate Language MSIL – сокращенно IL). Концептуально, язык MSIL похож на байт-код Java. Он также определяет набор инструкций, не зависимых от процессора ЭВМ, но между MSIL и байт-кодом Java имеются различия.
MSIL в отличие от байт-кода Java не интерпретируется, а компилируется с помощью JIT (just in time – в нужный момент) компилятора во внутренние коды процессора по мере необходимости. При этом время запуска программы мало отличается от времени запуска программы компилированной традиционным компилятором.
Это объясняется двумя причинами:
1. JIT – компилирует не всю программу сразу, а только тот кусок кода, который вызывается в данный момент (отсюда название компилятора just-in-time). Скомпилированный код сохраняется в ОЗУ и при следующем запуске этого куска кода перекомпиляции не происходит. JIT – компилятор – оптимизирует код также как и традиционный компилятор, но кроме этого оптимизирует код непосредственно для того процессора, на котором он выполняется.
В связи с этим фирма Microsoft даже ожидает повышения быстродействия работы программы.
C# — это основной язык для разработки в среде.NET.
1. Какие объективные предпосылки привели к разработке среды.NET Framework?
2. Краткая характеристика.NET Framework.
3. Что понимается под межъязыковой совместимостью в среде.NET Framework?
4. Каким образом достигается межъязыковая совместимость в среде.NET Framework?
5. Как в среде.NET Framework решается проблема «ада DLL»?
6. Что такое сборка? Какую информацию содержит сборка и как она используется при запуске программы на выполнение в среде.NET Framework?
7. Каковы процессы, происходящие при запуске программы на выполнение в среде.NET Framework?
8. В чем отличия и преимущества JIT – компилятора перед традиционными компиляторами?
9. Каковы корни языка C# — основного языка программирования среды.NET Framework?
Терминология и основные определения ООП
ООП – это метод программирования, позволяющий рассматривать концептуальную модель как набор объектов. Объектно-ориентированный подход в программировании – это средство для создания больших, сложных, а самое главное, работающих программ. Программа, при объектно-ориентированном подходе выполняется с помощью объектов.
Объекты – как в реальной жизни – обладают определенными свойствами. Эти свойства объектов определяются программистом. Свойства объектов описываются относительно небольшим по объему кодом, который легко поддается отладке и тестированию. Для создания и определения свойств объектов используются структуры и классы.
В C# понятие структуры (тип struct), унаследованной от языка C, получает дальнейшее развитие. Кроме член-данных структуры могут теперь включать в себя член-функции.
Классы — это новый тип данных, является расширением типа struct и образует абстрактный тип данных для ООП. Класс состоит из набора переменных (данных) и операций (методов или функций-членов класса), работающих с этими переменными.
Объекты – это экземпляры класса или структуры.
В C# структура является ограниченным по своим возможностям классом.
Инкапсуляция — это сокрытие информации о строении или деталях класса.
Класс включает в себя как данные, так и код (функции). Доступ к элементам класса управляем. Задача программиста, создающего новый тип данных — класс — скрыть как можно больше информации от пользователя класса.
Пользователю класса предоставляется (минимальная) необходимая и достаточная информация для использования класса: пользовательский интерфейс.
Класс для пользователя — это черный ящик с характерным поведением.
Наследование – это средство получения новых классов из существующих классов. Другими словами наследование – это способность класса наследовать свойства других классов.
Класс, от которого наследуется, называется родительским классом или базовым классом. Получившийся в результате наследования новый класс называется порожденным или производным классом.
Наследуя характеристики базового класса можно заставить порожденный класс расширить, изменить или использовать их без изменения.
Полиморфизм – это свойство кода С# вести себя по разному в зависимости от ситуации, возникающей в момент выполнения.
Полиморфизм – это скорее характеристика функций членов класса. Полиморфизм реализуется через архитектуру классов, но полиморфными могут быть только функции, а не весь класс.
Различают несколько видов полиморфизма:
1. Специальный полиморфизм
2. Параметрический полиморфизм
3. Чистый полиморфизм
Каждый вид полиморфизма реализуется с помощью различных механизмов, которые будут нами рассмотрены в соответствующих разделах.
Система типов C#
Система типов C# тесно интегрирована с системой общих типов –Common Type System (CTS) промежуточного языка IL среды.NET. В CTS согласно принципам ООП экземпляр любого типа данных является объектом с характерным для этого типа поведением. Попытки представить экземпляры всех типов в виде объектов предпринимались и ранее, но это обычно приводило к снижению скорости выполнения программы.
Разработчики CTS решили проблему производительности следующим образом: все типы в CTS делятся на две большие категории. Это деление осуществляется по способу хранения экземпляров типов в памяти ЭВМ. Первая категория это ссылочные типы, которые предназначены для хранения сложных типов данных. Типы по ссылке хранятся в памяти ЭВМ, называемой кучей.
Вторая категория данных – это объекты, хранящиеся в стеке, и называется типы по значению. Они применяются для хранения данных фиксированного размера. Все типы в CTS являются производными от базового типа – System.Object.
Предположим, что у нас имеется ссылочный тип с именем Reftype.
Для создания объекта ссылочного типа необходимо выполнить два шага:
1. объявить ссылку, например:
2. выделить память под объект этого типа с помощью оператора new:
myObj = new Reftype();
Оператор new выполняет для ссылочных типов два действия.
Во-первых, выделяет память под объект указанного типа, возвращая адрес (ссылку) объекта в памяти, во-вторых, вызывает конструктор объекта.
Конструктор – это специальный метод класса, который будет рассмотрен нами позже. Сама ссылка, т.е. адрес объекта, хранится в стеке, занимая минимальное место в памяти. При передаче объекта передается не сам объект, который может быть достаточно большим и сложным, а только ссылка на него (адрес).
При создании объекта типа по значению, для объекта сразу выделяется память в стеке. Оператор new здесь может применяться только для вызова конструктора. Использование переменной ссылочного типа до вызова оператора new, в отличие от базовых типов по значению, невозможно.
Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:
Источник: studopedia.ru
Запуск, возобновление и фоновые задачи
В этом разделе содержатся сведения по следующим вопросам:
- Что происходит при запуске, приостановке, возобновлении и завершении работы приложения универсальной платформы Windows (UWP).
- Запуск приложений с помощью URI или активации файла
- Использование служб приложений, позволяющих приложению универсальной платформы Windows (UWP) обмениваться данными и функциями с другими приложениями.
- Использование фоновых задач, позволяющих приложению UWP выполнять работу, даже если приложение не находится на переднем плане.
- Обнаружение подключенных устройств, запуск приложения на другом устройстве и взаимодействие с этим приложением на удаленном устройстве, путем создания единообразного пользовательского интерфейса на разных устройствах.
- Выбор правильной технологии для расширения возможностей и разделения на компоненты вашего приложения.
- Добавление и настройка экрана-заставки для приложения.
- Создание расширения для вашего приложения с помощью пакетов, которые можно установить из Microsoft Store.
Жизненный цикл приложений
В этом разделе описывается жизненный цикл приложения универсальной платформы Windows (UWP) для Windows 10 с момента его активации и до закрытия.
Жизненный цикл приложения | Узнайте о жизненном цикле приложения UWP и о том, что происходит при загрузке, приостановке и возобновлении работы вашего приложения системой Windows. |
Обработка предварительного запуска приложения | Узнайте, как обрабатывать предварительный запуск приложения. |
Обработка активации приложения | Узнайте, как обрабатывать активацию приложения. |
Обработка приостановки работы приложения | Узнайте, как сохранить важные данные приложения, когда система приостанавливает его работу. |
Обработка возобновления работы приложения | Узнайте, как обновить отображаемое содержимое, когда система возобновляет работу приложения. |
Освобождение памяти при переходе приложения в фоновый режим | Узнайте, как уменьшить объем используемой приложением в фоновом режиме памяти, чтобы работа приложения не прекратилась. |
Задержка приостановки приложения с помощью расширенного сеанса выполнения | Узнайте, как использовать расширенный сеанс выполнения для обеспечения работы приложения в свернутом состоянии |
Запуск приложений
Создание консольного приложения для универсальной платформы Windows | Узнайте, как создать приложение универсальной платформы Windows, выполняемое в окне консоли. |
Создание нескольких экземпляров приложения UWP | Узнайте, как создать приложение универсальной платформы Windows, позволяющее использовать несколько его экземпляров. |
В разделе Запуск приложения с помощью URI подробно описано, как использовать универсальный код ресурса (URI) для запуска приложения.
Запуск приложения по умолчанию для URI | Узнайте, как запускать приложение по умолчанию для универсального кода ресурса (URI). Универсальные коды ресурсов (URI) позволяют запустить приложение, чтобы выполнить определенную задачу. В этом разделе также приводится обзор множества схем URI, встроенных в Windows. |
Обработка активации URI | Узнайте, как зарегистрировать приложение в качестве стандартного обработчика определенного имени схемы универсального кода ресурса (URI). |
Запуск приложения для результатов | Узнайте, как запустить приложение из другого приложения и обмениваться данными между двумя приложениями. Эта процедура называется запуском приложения для результатов. |
Выбор и сохранение звуковых сигналов с помощью схемы URI ms-tonepicker | В этом разделе описывается схема URI ms-tonepicker и порядок ее использования для отображения средства выбора звуковых сигналов с целью выбора звукового сигнала, сохранения звукового сигнала и получения понятного имени звукового сигнала. |
Запуск приложения «Параметры» для Windows | Узнайте, как запустить приложение «Параметры» для Windows из вашего приложения. В этом разделе приводится описание схемы URI ms-settings. Используйте эту схему URI для запуска приложения «Параметры» для Windows на определенных страницах параметров. |
Запуск приложения Microsoft Store | В этом разделе описывается схема URI ms-windows-store. Ваше приложение может использовать эту схему URI для запуска приложения UWP на определенных страницах в Store. |
Запуск приложения «Карты Windows» | Узнайте, как запустить приложение «Карты Windows» из вашего приложения. |
Запуск приложения «Люди» | В этом разделе приводится описание схемы URI ms-people. Ваше приложение может использовать эту схему URI для запуска приложения «Люди» для конкретных действий. |
Поддержка привязки приложений к Интернету с помощью обработчиков URI приложения | Повышайте интерес пользователей к вашему приложению с помощью обработчиков URI приложения. |
В разделе Запуск приложения через активацию файла рассказывается о том, как настроить приложение для запуска при открытии определенного типа файла.
Запуск приложения по умолчанию для файла | Узнайте, как запускать приложение по умолчанию для файла. |
Обработка активации файла | Узнайте, как зарегистрировать приложение в качестве обработчика по умолчанию для определенного типа файла. |
См. другие статьи, связанные с запуском приложения, ниже.
Продолжение активности пользователей даже на разных устройствах | Обеспечьте интерес пользователей к вашему приложению на разных устройствах, запуская приложение с того места, где пользователь остановился. |
Запуск приложения с помощью автозапуска | Автозапуск можно использовать для добавления приложения в список вариантов при подключении пользователем устройств к компьютеру. Это могут быть как устройства томов, такие как USB-устройства флэш-памяти, SD-карты или DVD-диски, так и прочие устройства, такие как камеры или проигрыватели мультимедиа. |
Зарезервированные имена файлов и схем URI | В этом разделе перечислены зарезервированные имена файлов и схем URI, которые недоступны в приложении. |
Службы и расширения приложений
В разделе Службы приложений и расширения описывается, как интегрировать службы приложений с приложением UWP, чтобы разрешить общий доступ к данным и функциям между приложениями.
Создание и использование службы приложений | Узнайте, как написать приложение универсальной платформы Windows (UWP), которое может предоставлять службы другим приложениям UWP, и как использовать эти службы. |
Преобразование службы приложений для ее запуска в одном процессе с ведущим приложением | Преобразуйте код службы приложений, выполняемый в отдельном фоновом процессе, в код, выполняемый в одном процессе с поставщиком службы приложений. |
Расширение возможностей приложения за счет его служб, расширений и пакетов | Определите, какую технологию следует использовать для расширения и разбиения приложения на компоненты, и прочитайте краткий обзор каждого метода. |
Создание и использование расширения приложения | Создавайте и размещайте расширения приложений универсальной платформы Windows (UWP), расширяющие возможности приложения с помощью пакетов, которые пользователи могут установить из Microsoft Store. |
Фоновые задачи
В разделе Фоновые задачи показано, как обеспечить выполнение облегченного кода в фоновом режиме в ответ на триггеры.
Руководство по работе с фоновыми задачами | Убедитесь, что ваше приложение отвечает требованиям, необходимым для выполнения фоновых задач. |
Доступ к датчикам и устройствам из фоновой задачи | DeviceUseTrigger позволяет приложению UWP получать доступ к датчикам и периферийным устройствам в фоновом режиме даже тогда, когда приложение переднего плана приостановлено. |
Создание и регистрация фоновой задачи, выполняемой внутри процесса | Создание и регистрация фоновой задачи, которая запускается в том же процессе, что и приложение переднего плана. |
Создание и регистрация внепроцессной фоновой задачи | Создание и регистрация фоновой задачи, которая запускается в виде отдельного процесса из вашего приложения, и регистрация ее для выполнения, когда приложение находится не на переднем плане. |
Создание и регистрация фоновой задачи COM для приложения Win32 | Создайте фоновую задачу COM, которая может выполняться в основном процессе или вне процесса, когда упакованное приложение Win32 не запущено. |
Перенос фоновой задачи, выполняемой вне процесса, в фоновую задачу внутри процесса | Узнайте, как преобразовать выполняемую вне процесса фоновую задачу в фоновую задачу внутри процесса, выполняемую в том же процессе, что и ваше приложение переднего плана. |
Отладка фоновой задачи | Узнайте, как отладить фоновую задачу, выполнив в том числе активацию фоновой задачи и трассировку отладки в журнале событий Windows. |
Объявление фоновых задач в манифесте приложения | Вы можете разрешить использование фоновых задач, объявив их как расширения в манифесте приложения. |
Регистрация фоновых задач группы | Изолируйте регистрацию фоновой задачи с помощью групп. |
Обработка отмененной фоновой задачи | Узнайте, как создать фоновую задачу, которая распознает запросы на отмену, прекращает работу и сообщает приложению об отмене, используя постоянное хранилище. |
Отслеживание хода выполнения и завершения фоновых задач | Узнайте, как ваше приложение распознает ход выполнения и завершение фоновой задачи. |
Оптимизация фоновой активности | Узнайте, как снизить потребление энергии в фоновом режиме и как взаимодействовать с параметрами пользователя для фоновых задач. |
Регистрация фоновой задачи | Сведения о создании функции, которую можно многократно использовать для безопасной регистрации большинства фоновых задач. |
Реагирование на системные события с помощью фоновых задач | Узнайте, как создавать фоновые задачи, отвечающие на события SystemTrigger. |
Запуск фоновой задачи по таймеру | Узнайте, как запланировать однократное выполнение фоновой задачи или периодически запускать фоновую задачу. |
Выполнение в фоновом режиме в течение неограниченного срока | Используйте возможность для выполнения фоновой задачи или расширенного сеанса выполнения в фоновом режиме в течение неограниченного срока. |
Запуск фоновой задачи в приложении | Узнайте, как использовать ApplicationTrigger для активации фоновой задачи в приложении. |
Задание условий выполнения фоновой задачи | Узнайте, как задать условия, которые управляют запуском выполнения фоновой задачи. |
Передача данных в фоновом режиме | Используйте фоновую передачу данных API для копирования файлов в фоновом режиме. |
Обновление живой плитки из фоновой задачи | Используйте фоновую задачу для обновления живой плитки вашего приложения свежим содержимым. |
Использование триггера обслуживания | Узнайте, как использовать класс MaintenanceTrigger для выполнения облегченного кода в фоновом режиме, когда устройство подключено к сети. |
Удаленные системы
В разделе Подключенные приложения и устройства (Project Rome) описано, как использовать платформу удаленных систем для обнаружения удаленных устройств, запуска приложения на удаленном устройстве и взаимодействия со службой приложений на удаленном устройстве.
Обнаружение удаленных устройств | Узнайте, как обнаруживать устройства, к которым можно подключиться. |
Запуск приложения на удаленном устройстве | Узнайте, как запустить приложение на удаленном устройстве. |
Обмен данными с удаленной службой приложений | Узнайте, как взаимодействовать с приложением на удаленном устройстве. |
Подключение устройств с помощью удаленных сеансов | Предоставляйте общие возможности на нескольких устройствах за счет их объединения через удаленный сеанс. |
Экраны-заставки
В разделе Экраны-заставки описывается, как установить и настроить экран-заставку вашего приложения.
Добавление экрана-заставки | Задайте изображение экрана-заставки и цвет фона вашего приложения. |
Более продолжительное отображение экрана-заставки | Увеличьте длительность отображения экрана-заставки, создав и использовав расширенный экран-заставку для приложения. Этот расширенный экран имитирует экран-заставку, отображаемый при запуске приложения, и его можно настраивать. |
Источник: learn.microsoft.com
Как Android запускает MainActivity
Недавно я провел исследование о main() методе в Java и то, как он служит точкой входа для любого приложения Java. Это заставило меня задуматься, а как насчет Android-приложений? Есть ли у них основной метод? Как они загружаются? Что происходит за кулисами до выполнения onCreate()?
Майкл Бэйли очень подробно рассказал о том, как работает Main Thread, так что это быстрый обзор его доклада плюс дополнительная информация из Android Open Source Project (AOSP).
В этой статье мы рассмотрим:
- Что происходит от нажатия на иконку приложения до запуска MainActivity
- Найдем основной метод приложения и узнаем, как основной поток (он же UI, он же Main Thread) получает свое назначение.
- Рассмотрим роль, которую играют Looper //Modification — Removed unrelated initializers. //Android initializes some tracers, event loggers, enviroment initializers, trusted certificates and updates the process’ state Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) < sMainThreadHandler = thread.getHandler(); >// More logging // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException(«Main thread loop unexpectedly exited»); >
Рисунок 2: Метод main() в ActivityThread, который служит точкой входа для запуска вашего приложения.
Как видно в коде: метод main() выполняет три важных дела:
1. Подготавливает основной Looper (MainLooper) (Process 2)
2. Настройка Handler’a (Process 4)
3. Вызов метода Looper.loop() в главном потоке (MainThread) (Process 6)2.1 Подготовка main looper (Process 2–3)
Основной Looper задается вызовом Looper.prepareMainLooper() (см. Строку 8 в коде). Это отмечает текущий случайный поток, который выполняет всю работу по вызову метода main() в качестве основного потока приложений. Именно так и именно здесь определяется знаменитый главный поток для приложения в Android!
2.2 Вызов Handler’a (Process 4-5)
Внутри класса ActivityThread существует приватный внутренний класс H, да-да, все верно, просто H, который наследуется от класса Handler (см. рис. 4 и 7). В 12й строке экземпляр H-обработчика устанавливается как главный Handler потока. Что очень интересно знать о классе H, как вы сами увидите позже, это то, что он содержит более 50 определений состояния/событий, в которых может находиться ваше приложение, например LAUNCH_ACTIVITY, PAUSE_ACTIVITY, BIND_SERVICE и т.д.
2.3 Вызов метод loop() у Looper’а (Process 6–7)
После назначения главного потока в этом же главном потоке, для того чтоб мы могли в нем что-то выполнять, вызывается метод Looper.loop() (см. Строку 20). Это начинает выполнение сообщений в очереди сообщений Loopers. Теперь главный поток запущен и может начать обработку задач из очереди.
Обратите внимание, что в строке 18, если выполнение кода пойдет дальше чем Looper.loop() в 17 строке вдруг и приложение выйдет из цикла, то будет брошено исключение RuntimeException. Это говорит о том, что метод loop() в идеале никогда преждевременно не заканчивается. Мы увидим как это в следущем разделе.
3. Бесконечный loop() в Looper’е (Process 7,8,9)
/** * AOSP * Looper class */ public static void loop() < final Looper me = myLooper(); if (me == null) < throw new RuntimeException(«No Looper; Looper.prepare() wasn’t called on this thread.»); >final MessageQueue queue = me.mQueue; //code removed for (;;) < Message msg = queue.next(); // might block if (msg == null) < // No message indicates that the message queue is quitting. return; >> >
Рисунок 3: Код внутри метода loop() в классе Looper’e
Как мы видим в коде, в методе Looper.loop() есть очередь сообщений (строка 10) и внутри цикла вызывается queue.next(). MessageQueue заполняется Handler-‘ом, о котором мы говорили в предыдущем разделе (см. Process 8). Обратите внимание на интересное описание условия в цикле for — здесь нет аргументов, только две точки с запятой говорят что это бесконечный цикл. Поэтому Looper в идеале никогда не заканчивается, если данное сообщение не null.
Итак, теперь мы определили главный поток, выполняемый благодаря Looper, мы также видели, что Handler добавляет сообщения в цикл Looper.loops() и обрабатывает сообщения. Давайте посмотрим, как они вместе вызывают нашу Activity.
4. Запуск MainActivity (Process 10 to 15)
Важно помнить, что этот бесконечный цикл и обработка сообщений выполнялись в main() методе класса ActivityThread, потому что именно там они были вызваны (см. в коде строки с 12 по 17). Мы поверхностно просмотрели Loopers, MessageQueues и Handlers, чтобы вникнуть в контекст. Итак, давайте вернемся к классу ActivityThread, в частности, к внутреннему классу H, о котором мы говорили ранее, который действует как основной Handler главного потока.
Итак, у нас есть Looper, передающий сообщения нашему Handler’у, давайте узнаем, как эти сообщения обрабатываются. Это делается внутри класса H. Этот класс содержит метод handleMessage(Message msg). Помните, что все классы, которые наследуются от Handler, должны переопределить этот метод.
/** * Retrieved from AOSP * H class embedded in the ActivityThread class */ private class H extends Handler < //Several Application State Identifiers . public void handleMessage(Message msg) < //other code switch (msg.what) < case LAUNCH_ACTIVITY: < //create Activity records handleLaunchActivity(r, null, «LAUNCH_ACTIVITY»); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); . //handle other cases e.g ResumeActivity, PauseActivity, BindService, UnbindService etc. >> > >
Рисунок 4: Приватный внутренний класс H и его handleMessage() метод
Как видно в коде, в 8й строке есть оператор switch, в котором определяется обработка входящего сообщения по его содержимому.
Один из случаев (cases) включает в себя запуск активности (строка 11), что интересно, так это то, что этот метод предназначен для обработки около 50 случаев, которые варьируются от возобновления, приостановки, запуска Activity, привязки Service’ов, обработки Receiver’ов, предоставления предупреждений lowMemory или trimMemory, когда память устройства заполняется и т. д.
В case LAUNCH_ACTIVITY вызывается метод handleLaunchActivity(), как показано в строке 13, см Process11 на схеме. Затем этот метод вызывает другой метод, называемый performLaunchActivity(), который возвращает объект Activity (см. Рис. 5, строка 7).
/** * Retrieved from AOSP. * ActivityThread class */ private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) < //. initialize graphics,do some logging, call GC if need be, etc Activity a = performLaunchActivity(r, customIntent); //. handle how to resume an existing activity >
Рисунок 5: Метод handleLaunchActivity() в котором создается Activity
Метод performLaunchActivity() добавляет в Activity важную информацию, такую как Instrumentation, Context, Component, а также Intent; а также задает Application. Затем этот метод вызывает Instrumentation.callActivityOnCreate() (Process 13), который является последним этапом перед вызовом метода onCreate() в Activity (Process 14-15, см. Рисунок 5 (код), строки 8-10).
Рисунок 6: Класс Instrumentation наконец запускает Activity
На данный момент ваша Activity загружена c множеством полезных переменных и методов, которые можно использовать для создания вашего нового удивительного приложения для Android! Все это благодаря ActivityThread, умной работе Handler’a и Looper’a, и огромному классу Activity в 7600 строк кода, который позволяет аттачить фрагменты, получить контекст и легко управлять View’s — и много еще чего.
Примерно так наша Activity и создается!
Источник: habr.com