ПРОграммирование под Android
Страницы
28 ноября 2014 г.
Layouts (компоновки). Теория
Переходим к изучению Layouts. Или как часто переводят разметка, компоновка или представление элементов пользовательского интерфейса.
Все элементы пользовательского интерфейса в приложениях Андроид создаются с использованием объектов View и ViewGroup.
Класс View является базовым классом для ViewGroup и состоит из коллекции объектов View. Есть множество типов представлений и групп представлений, каждый из которых является потомком класса View.
На платформе Android необходимо определить пользовательский интерфейс для каждой Активности, используя иерархии узлов View и viewGroup. Это дерево иерархии может быть и простым, и сложным — в зависимости от требований к графическому интерфейсу приложения.
При запуске Активности система должна получить ссылку на корневой узел дерева разметки, который будет использоваться для прорисовки графического интерфейса на экране мобильного устройства. Для этого в методе onCreate() необходимо вызвать метод setСontentView(), передав ему в качестве параметра ссылку на ресурс разметки в следующем виде:
R.layout.layout_file_name
Например, если ваша XMLразметка сохранена как main.xml, вы загружаете разметку для Activity примерно так:
Прорисовка начинается с корневого узла дерева разметки. Затем последовательно прорисовываются дочерние представления дерева разметки. Это означает, что родители будут прорисовываться раньше, чем их дочерние представления, — т. е. по окончании процесса прорисовки родители будут находиться на заднем плане по отношению к дочерним узлам.
Разметка, как было сказано, — это архитектура расположения элементов интерфейса пользователя для конкретного окна, представляющего Активность. Она определяет структуру расположения элементов в окне и содержит все элементы, которые предоставляются пользователю программы. Разметку можно объявлять двумя способами:
- объявить элементы пользовательского интерфейса в XML. Android обеспечивает прямой XMLсловарь, который соответствует классам View и ViewGroup;
- создать разметку для окна в коде программы во время выполнения — инициализировать объекты Layout и дочерние объекты View, ViewGroup и управлять их свойствами программно.
Android позволяет использовать каждый из этих методов в отдельности или оба сразу для объявления и управления пользовательским интерфейсом в приложении. Например, можно объявить заданные по умолчанию разметки вашего приложения в XML, включая экранные элементы, которые появятся в них, и их свойства, а затем добавить код в вашем приложении, который во время выполнения изменит состояние объектов на экране, включая объявленные в XML.
ADT-плагин для Eclipse предлагает удобный инструментарий — визуальный редактор разметки Layout Editor, который применяется для создания и предварительного просмотра создаваемых файлов разметки, которые находятся в каталоге res/layout/ проекта.
Самый общий способ определять разметку и создавать иерархию представления— в XML файле разметки. XML предлагает удобную структуру для разметки, похожую на HTML разметку WEB страницы.
Преимущество объявления пользовательского интерфейса в XMLфайле состоит в том, что это дает возможность отделить представление приложения от программного кода, который управляет поведением приложения. Ваше описание пользовательского интерфейса является внешним по отношению к программному коду, что означает, что вы можете изменять пользовательский интерфейс в файле разметки без необходимости изменения вашего программного кода.
Например, вы можете создавать XML разметки для различных ориентаций экрана мобильного устройства (portrait, landscape), размеров экрана и языков интерфейса. Дополнительно, объявление разметки в XML файле облегчает возможность по визуализации структуры вашего пользовательского интерфейса, что упрощает отладку приложения.
Каждый элемент в XML является объектом View или ViewGroup (или его потомком). Объекты view— листья в дереве, объекты ViewGroup— ветви. Вы можете также создавать объекты View и viewGroups в Java-коде, используя метод addview (View), чтобы динамически вставлять новые объекты view и ViewGroup в существующую разметку.
Используя различные виды групп представлений, можно структурировать дочерние представления и группы представлений многими способами в зависимости от требований к графическому интерфейсу приложения. Некоторые стандартные группы представлений, предлагаемые Android (называющиеся разметками), включают LinearLayout, RelativeLayout, TableLayout и др. (будут подробно описаны позднее). Каждый из этих типов разметки предлагает уникальный набор параметров, которые используются, чтобы определить позиции дочерних представлений и структуру разметки на экране.
Объявление в XML
Используя XML словарь Android, можно быстро проектировать пользовательский интерфейс разметки и экранные элементы, которые он содержит, тем же самым способом, которым вы создаете web страницы в HTML — с рядом вложенных элементов.
Каждый файл разметки должен содержать только один корневой элемент, который должен быть объектом View или ViewGroup. Как только вы определили корневой элемент, вы можете добавить дополнительные объекты разметки или виджеты как дочерние элементы, чтобы постепенно формировать иерархию элементов, которую определяет создаваемая разметка.
Самый простой способ объяснять эту концепцию состоит в том, чтобы показать образец.
Общая структура XML файла разметки проста: это — дерево XML элементов, где каждый узел представляет имя класса View (в нашем примере только один элемент View— TextView). Вы можете использовать имя любого класса, производного от класса View, как элемент в XML разметках, включая ваши собственные классы. Эта структура позволяет быстро создавать пользовательский интерфейс, используя более простую структуру и синтаксис, чем при создании разметки в программном коде.
В вышеупомянутом XML примере есть корневой элемент и только один дочерний элемент View. TextView (текстовое поле), который имеет атрибуты. Описание некоторых из этих атрибутов приведем ниже:
- xmlns:android – декларация пространства имен XML, которая сообщает среде Android, что вы ссылаетесь на общие атрибуты, определенные в пространстве имен Android. В каждом файле разметки у корневого элемента должен быть этот атрибут со значением «http://schemas.android.com/apk/res/android»
- android:layout_width – этот атрибут определяет, сколько из доступной ширины на экране должен использовать этот объект View (или View Group). В нашем случае он — единственный объект, таким образом, можно растянуть его на весь экран, которому в данном случае соответствует значение mutch_parent
- android:layout_height – аналогично android:layout_width, за исключением того, что он ссылается на доступную высоту экрана
- android:text – устанавливает текст, который должен отобразить Textview. В этом примере используется строковый ресурс вместо жестко закодированного строкового значения. Строка hello определена в файле res/values/strings.xml. Это рекомендуемая практика для использования строковых ресурсов в ваших приложениях, потому что она делает локализацию приложения на другие языки более простой, без потребности кодировать напрямую изменения в файле разметки
Каждый объект View и ViewGroup поддерживает свое собственное разнообразие XML атрибутов. Некоторые атрибуты являются определенными только в объекте View (например, Textview поддерживает атрибут textSize), но эти атрибуты могут также наследоваться любыми объектами View, которые расширяют этот класс. Некоторые атрибуты являются общими ко всем объектам View, потому что они унаследованы от корневого класса View (подобно атрибутам id, layout_width, layout_height).
В общем, XML словарь элементов пользовательского интерфейса близок к структуре классов и методов этих элементов, где имя элемента соответствует имени класса, а атрибуты элемента — методам этого класса. Фактически, соответствие является часто настолько точным, что легко предположить без обращения к документации Android, какой XML атрибут передает метод класса или, наоборот, какой метод класса соответствует конкретному XML элементу.
Соответствие XML атрибутов и методов в классах представлений
Любой объект View в коде программы можно связать с объектом из файла разметки, однозначно определив элемент пользовательского интерфейса в пределах дерева. Когда приложение откомпилировано, на этот идентификатор ссылаются как на целое число, но идентификатор представления обычно обозначается в XML файле разметки как строка в атрибуте id. Синтаксис для идентификатора элемента в XMLтеге следующий:
Символ @ в начале строки указывает, что синтаксический анализатор XML должен проанализировать и развернуть остальную часть строки идентификатора и определить это выражение как ресурс идентификатора. Символ + означает, что это — новое имя ресурса, которое должно быть создано и добавлено к нашим ресурсам в файл R.java, который среда Android автоматически генерирует для проекта, как показано в листинге.
Если в программном коде мы не работаем с некоторыми элементами пользовательского интерфейса, создавать идентификаторы для них необязательно, однако определение идентификаторов для объектов представления важно при создании RelativeLayout (относительной разметки). В RelativeLayout расположение представлений может определяться относительно другого представления, на которое ссылаются через его уникальный идентификатор:
android:id=»@+id/TextViewOl»
Требование к уникальности идентификаторов не распространяется на все дерево представлений, но они должны быть уникальны в пределах части дерева (которая часто может быть и полным деревом представлений, так что лучше создавать полностью уникальные идентификаторы, если это возможно).
Существуют следующие стандартные типы разметок, которые вы можете использовать в создаваемых приложениях:
- FrameLayout;
- LinearLayout;
- TableLayout;
- RelativeLayout;
- GridLayout.
Подобно всем разметкам, все они являются подклассами viewGroup и наследуют свойства, определенные в классе View.
Что самое интересное весь этот материал взят от сюда, ну кроме второго абзаца с верху который я сам перевел с альма-матер. Кто у кого стянул текст не понятно. То ли Голощапов, то ли этот сайт. Но на сайте инфы больше.
Источник
Архитектура Android-приложений. Часть III — основные части приложения
Итак, мы уже говорили о происхождении архитектуры ОС Android и о шаблонах, реализованных в этой архитектуре. Теперь настала пора поговорить о том, из чего состоит Android-приложение.
В этой статье будут представлены основные «персонажи» архитектуры Android-приложения.
В общем случае, Android-приложение состоит из:
- Java-классов, являющихся подклассами основных классов из Android SDK (View, Activity, ContentProvider, Service, BroadcastReciever, Intent) и Java-классов, у которых нет родителей в Android SDK.
- Манифеста приложения
- Ресурсов наподобие строк, изображений и т.п.
- Файлов
Java классы
На следующей диаграмме представлена иерархия основных классов из Android SDK, с которыми предстоит иметь дело разработчику:
На самом деле классов намного больше, но это основные. Выделенные жёлтым — те, с которыми разработчик работает непосредственно (в частности, наследуются от них). Остальные так же важны, но они реже используются напрямую.
View — базовый класс для всех виджетов пользовательского интерфейса (GUI widgets). Интерфейс Android-приложения представляет собой дерево экземпляров наследников этого класса. Можно создать это дерево программно, но это неправильно. Пользовательский интерфейс определяется с помощью XML (файлы слоёв, layout files), а во время исполнения автоматически превращается (inflate, термин Android) в дерево соответствующих объектов.
Класс Activity и его подклассы содержат логику, лежащую за пользовательским интерфейсом. При ближайшем рассмотрении этот класс соответствует ViewModel в архитектурном шаблоне Model-View-ViewModel (MVVM). Отношение между подклассом Activity и пользовательским интерфейсом — это отношение один к одному; обычно каждый подкласс Activity имеет только один связанный с ним слой пользовательского интерфейса, и наоборот. Activity имеет жизненный цикл.
В течении жизненного цикла Activity может находиться в одном из трёх состояний:
- Активно и выполняется — этот пользовательский интерфейс находится на переднем плане (говоря технически — на вершине стека активити)
- Приостановлено — если данный интерфейс пользователя потерял фокус, но всё ещё видим. В таком состоянии никакой код не выполняется.
- Завершено — если интерфейс пользователя невидим. В таком состоянии код не выполняется.
Код активити выполняется только когда соответствующий интерфейс пользователя видим и имеет фокус. Нет гарантии, что объект Activity и связанные с ним объекты находятся в памяти, когда активити приостановлено или завершено (очень важно помнить об этом; ранее мы уже обсуждали этот момент управления памятью в Android).
Класс ContentProvider и его подклассы представляют model в архитектуре MVVM. В большинстве практических случаев это обёртка над базой данных SQLite с немного причудливым способом доступа на основе URI. Теоретически, никто не мешает разработчику создать ContentProvider на основе чего-то ещё, кроме базы данных. Тем не менее, существующий метод query() контент-провайдера возвращает объект Cursor, который крайне похож на JDBC ResultSet интерфейсом и тем, как он работает. Поэтому вряд ли кто-то усомнится, что настоящее назначение контент-провайдеров — инкапсулировать базу данных.
Я не знаю, как комманда Android пришла к такому дизайну, но, по-моему, здесь соединены две хороших, но не слишком совместимых идеи.
И вот почему я так считаю. Основная идея контент-провайдеров, похоже, базируется на архитектуре AJAX приложений. AJAX приложения обычно используют архитектуру MVVM, где модель представлена как URI на стороне сервера (тем не менее, это изменилось с поялвинем HTML5, который позволяет хранить данные локально). В самом деле, тот факт, что контент-провайдеры запрашиваются с помощью URI и создают расширение с помощью типов MIME указывает на то, что в основе лежит AJAX. Напомню, ребята из Google создали большое количество AJAX приложений, таких как Gmail, Google Docs и т.п., поэтому вполне естественно, что идеи заимствовались из архитектуры AJAX.
Возможно, кто-то ещё пришёл с ещё одной отличной идеей: как было бы здорово иметь полноценную реляционную базу на мобильном устройстве! (замечу, это было примерно в 2005 году, когда мобильные телефоны были намного слабее, чем сейчас). И, как результат, они соединили две хороших идеи в один класс ContentProvider. Как это обычно и случается в разработке ПО, соединение двух хороших идей не всегда даёт в результате хорошую идею; в случае Android мы имеем несколько обескураживающий дизайн контент-провайдеров.
Класс Service и его подклассы я затрудняюсь как-то классифицировать. Я думаю, ребята из Google испытывают те же трудности (прочтите, пожалуйста, их документацию). Их классификация, в основном, говорит, чем этот класс не является. Я лично думаю, что сервис — это разновидность Model, обслуживающая несколько иные варианты использования, нежели ContentProvider.
По-моему, архитектурный дизайн Android Service навеян сервисами OSGI.
Думаю, сервисы были созданы ребятами из Google как решение логической проблемы, возникшей из-за модели потоков Android.
Подумайте над этим: Activity активно и выполняется только когда его пользовательский интерфейс находится на переднем плане. Как только интерфейс другого Activity закрывает собой текущее, последнее останавливается, даже если оно что-то делало. А что, если вам нужно выполнять некую операцию, даже если процесс, которые её выполняет, не на переднем плане? С помощью Activity вы не сможете этого сделать. Вы не сможете это сделать и с помощью ContentProvider, поскольку у них нет собственного жизненного цикла, и они могут выполняться только пока Activity, использующее его, активно.
И тут на помощь приходят сервисы. Они могут выполняться даже когда процесс, в котором они работают, не на переднем плане. Так, если вы разрабатываете активити, выполняющее растянутую во времени операцию, которая должна завершиться даже работая в фоне, вы должны создать Service, реализующий эту операцию, и запустить его из Activity.
Service так же имеет жизненный цикл. Это означает, что он может быть инстанцирован и запущен Android-приложением по некому условию (мы обсудим это позже).
Как я уже упоминал, Service, как model, приследует более общие цели, нежели ContentProvier. Он может использовать базу данных, но его API не связано с БД, как в случае ContentProvider. В большинстве случаев сервисы используются для связи с внешними серверами.
Класс BroadcastReceiver и его подклассы представляют собой «подписчика» в механизме взаимодейтсвия издатель/подписчик, реализованном в архитектуре Android.
Мы уже говорили о механизмах взаимодействия в предыдущей статье.
Конечно, разработчик под Android не ограничен одним только расширением классов из Android SDK. Он может писать собственные классы так, как захочет. Но все они будут только хелперами («helper classes») для классов из Andoird SDK.
Манифест Android
Манифест Android — ещё одна важная часть Android-приложения. Идея была навеяна манифестами плагинов для Eclipse.
Манифест Android представляет собой XML файл и выполняет несколько функций. Вот как их описывает Google:
- Определяет имя Java-пакета приложения. Имя пакета представляет собой уникальный идентификатор для приложения.
- Описывает компоненты приложения — активити, сервисы, броадкаст-ресиверы и контент-провайдеры. Определяет имена классов, реализующие каждый из компонентов и оглашает их возможности (например, какие Intent-сообщения они могут обрабатывать). Эти объявления позволяют системе Android знать, какие компоненты и при каких условиях могут быть запущены.
- Предопределяет процессы, которые будут содержать компоненты приложения.
- Объявляет разрешения, которые приложение должно иметь для доступа к защищённым частям API и взаимодействия с другими приложениями.
- Также объявляет разрешения, которые требуются для доступа к компонентам приложения.
- Перечисляет классы Instrumentation, которые предоставляют профайлинг и другую информацию во время работы приложения. Эти объявления присутствуют в манифесте только пока приложение разрабатывается и тестируется; они удаляются перед публикацией приложения.
- Объявляет минимальный уровень Android API, который требует приложение.
- Перечисляет библиотеки, с которыми приложение должно быть связано.
Обратите внимание на второй пункт. Имеется ввиду, что если некий класс расширяет Activity, ContentProvider, BroadcastReceiver или Service в вашем приложении, этот класс не может быть использован до тех пор, пока он не описан в манифесте.
Ресурсы
Каждое современное GUI приложение в той или иной форме использует ресурсы. Android-приложения — не исключение. Они используют следующие типы ресурсов:
- Изображения
- Слои GUI (XML файлы)
- Объявления меню (XML файлы)
- Текстовые строки
Способ, которым ресурсы связываются с Android-приложением — это что-то необычное. Как правило, в Java ресурсы идентифицируются строками. Такие строки могут содержать, например, путь и имя файла, содержащего изображение, или ID данной строки и т.п. Проблема в том, что ошибки в таких ссылках не могут быть обнаружены в процессе трансляции кода.
Давайте рассмотрим следующий пример. Файл с именем mybutton.png содержит картинку для кнопки. Разработчик совершает ошибку и набирает mybuton.png, ссылаясь на ресурс из кода. Как итог, код пытается использовать несуществующий ресурс, но компиляция пройдёт успешно. Ошибка может быть обнаружена только в ходе тестирования (а может и не быть обнаружена вовсе).
Ребята из Google нашли элегантное решение этой проблемы. При сборке Android-приложения генерируется специальный Java-класс с именем R (всего лишь одна буква). Этот класс содержит несколько static final наборов данных. Каждый такой набор данных — ссылка на отдельный ресурс. Эти ссылки используются в коде приложения для связи с ресурсами. Теперь каждая ошибка в ссылке на ресурсы проявляет себя в процессе компиляции.
Файлы
Android-приложение использует несколько разных типов файлов:
- Файлы «общего назначения»
- Файлы БД
- Файлы Opaque Binary Blob (OBB) (они представляют собой зашифрованную файловую систему, которая может быть монтирована для приложения)
- Закешированные файлы
Хотя, в конечно итоге, все они только файлы Linux, имеет смылсл рассматривать их как отдельные типы файлов только в разрезе обработки их различным API и отдельного хранения. Также они отделены от файлов, хранящихся во внутреннем или внешнем хранилище (последнее может отсутствовать или исчезнуть/появиться в любой момент).
API для работы с файлами реализован классом Context, от которого порождены классы Activity и Service. Этот класс уже обсуждался нами здесь.
На сегодня это всё. В следующей статье мы поговорим о том, как различные части Android-приложения взаимодействуют между собой.
Источник