Android studio свойства проекта

Урок 1. Введение

В этом уроке я подробно расскажу о Dagger и его возможностях. Мы разберем, что такое Component и Module, подключим Dagger к проекту, и сделаем несколько простых примеров

Зачем нужен Dagger

Если вы хотите снизить зависимость объектов друг от друга и упростить написание тестов для вашего кода, то вам подойдет паттерн Dependency Injection. А Dagger — это библиотека, которая поможет в реализации этого паттерна. В этом курсе я опишу использование библиотеки Dagger версии 2 (далее по тексту даггер).

Плюсы даггера в сравнении с другими библиотеками:
— генерирует код несложный для понимания и отладки
— проверяет зависимости на этапе компиляции
— не создает проблем при использовании proguard

Сразу скажу, что тема нетривиальная и у вас могут возникать вопросы типа «а что будет, если сделать так?». Рассмотреть все случаи в рамках этого курса я не смогу. Поэтому очень рекомендую вам создавать примеры и на них проверять, как все это работает в том или ином случае. Это поможет вам лучше понять теорию.

Пример

Чтобы понять, зачем нам может понадобиться Dependency Injection и даггер, давайте рассмотрим небольшой пример. В нем мы смоделируем ситуацию, когда создание одного объекта может потребовать создание еще нескольких.

Пусть в нашем приложении есть MainActivity и, в соответствии с паттерном MVP, для него есть презентер. Презентеру для работы нужны будут некие UserController и DataController. Т.е. нам надо будет создать два этих объекта перед тем, как создать презентер. Но для создания двух этих объектов нам, в свою очередь, нужны объекты ApiService и SharedPreferences. А для создания ApiService нужны RestAdapter, RestAdapter.Builder, OkHttpClient и Cache.

В обычной реализации это может выглядеть так:

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

Выглядит это все не очень красиво, а главное — неправильно. Activity ничего не должно знать о кэшах, сервисах, контроллерах и прочем. Activity знает только презентер и должно получать его в готовом виде.

Как вариант — можно весь этот создающий код поместить в сам презентер. Т.е. Activity только создает презентер, а он уже пусть внутри себя создает все остальные объекты. Так сделать можно, но это тоже неправильно, потому что нарушает принцип Dependency Injection: презентер не должен создавать эти объекты, он их должен получать готовыми. Да и написать нормальные тесты для такого презентера будет затруднительно.

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

Даггер как раз является таким механизмом. При его использовании код в Activity будет выглядеть так:

Разумеется, код создания объектов никуда не исчез. Но он разделен на части и вынесен из Activity в специальные отдельные классы, к которым даггер имеет доступ. В итоге мы просто вызываем метод getMainActivityPresenter, чтобы получить презентер. А даггер под капотом уже сам создаст этот объект и всю необходимую для него иерархию объектов.

Теория

Теперь давайте смотреть, как работает даггер изнутри.

Возьмем все тот же пример с Activity и Presenter. Т.е. когда Activity для своих нужд создает объект Presenter.

Обычая схема создания будет выглядеть так:

Т.е. Activity создает Presenter самостоятельно

При использовании даггера схема будет выглядеть так:

Activity -> Component -> Module -> Presenter

Activity обращается к компоненту (appComponent в примере выше), компонент с помощью модулей создает Presenter (и все остальные необходимые для этого объекты) и возвращает его в Activity.

Модули и компоненты — это два ключевых понятия даггера.

Модули — это просто классы, в которые мы выносим (из Activity) код создания объектов. Обычно каждый модуль включает в себя создание объектов близких по смыслу.

Модуль UserModule будет содержать в себе код создания объектов, связанных с пользователями, т.е. UserController.

Модуль NetworkModule — объекты OkHttpClient и ApiService.

Модуль StorageModule — объекты DataController и SharedPreferences

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

Процесс работы даггера можно сравнить с обедом в McDonalds. Т.е. по аналогии со схемой даггера:

Activity -> Component -> Module -> Presenter

схема McDonalds выглядит так:

Клиент -> Кассир -> Производственная линия -> Заказ (Бигмак/Картошка/Кола)

Рассмотрим подробнее шаги этих схем:

McDonalds Даггер
Клиент определился, что его заказ будет состоять из бигмака, картошки и колы, и он говорит об этом кассиру Activity сообщает компоненту, что ему понадобится Presenter
Кассир ходит по производственной линии и собирает заказ: берет бигмак, наливает колу, насыпает картошку Компонент использует модули, чтобы создать все необходимые объекты, которые понадобятся для создания Presenter
Кассир комплектует заказ в пакет или на поднос и выдает его клиенту Компонент в итоге получает от модулей требуемый объект Presenter и отдает его Activity
Читайте также:  Что такое busybox для андроид

Практика

Теперь на простом примере посмотрим, как создавать модули и компоненты, и как с их помощью Activity будет получать требуемые объекты.

В этом курсе все примеры будут на Kotlin.

Подключение

Для начала подключите плагин kapt. Это делается в самом начале файла build.gradle модуля

Подключить можно так:

Добавьте в раздел dependencies файла build.gradle модуля строки:

Объекты

В качестве объектов, которые мы будем запрашивать от даггера, используем пару классов: DatabaseHelper и NetworkUtils.

Их реализация нам сейчас не важна, оставляем их пустыми.

Предположим, что эти объекты будут нужны нам в MainActivity.

Презентер пока не используем, чтобы не усложнять пример.

Чтобы получить эти объекты с помощью даггера, нам нужно создать модули и компонент.

Модули

Создаем модули, которые будут уметь предоставлять требуемые объекты. Именно в модулях мы и пишем весь код по созданию объектов. Это обычные классы, но с парой аннотаций.

Модуль для DatabaseHelper:

Модуль для NetworkUtils:

Аннотацией @Module мы сообщаем даггеру, что этот класс является модулем. А аннотация @Provides указывает, что метод является поставщиком объекта.

Таким образом мы предоставляем даггеру информацию о том, как создавать объекты DatabaseHelper и NetworkUtils. Нам больше не надо будет самим создавать их. Теперь, где бы они нам не понадобились, мы сможем просто попросить эти объекты у даггера, и он создаст их и предоставит нам.

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

Компонент

Модули готовы, теперь создаем компонент. Для этого нам необходимо создать интерфейс:

Данный интерфейс описывает пустой компонент, который пока ничего не умеет.

При компиляции проекта, даггер найдет этот интерфейс по аннотации @Component и сгенерирует класс DaggerAppComponent (Dagger + имя интерфейса), который станет реализацией этого интерфейса. Этот класс и будет потом создавать объекты и возвращать их нам.

После того как даггер создал нам класс компонента, нам необходимо создать экземпляр этого класса. Это можно сделать, например, в Application классе (не забудьте добавить его в манифест):

У класса компонента есть метод create, которым мы создаем его экземпляр.

Можно, кстати, сделать чуть короче:

На этом месте ваша среда разработки, возможно, будет ругаться на класс DaggerAppComponent. Так может происходить, потому что класса DaggerAppComponent пока не существует. Мы описали интерфейс компонента AppComponent, но нам надо скомпилировать проект, чтобы даггер создал этот класс-компонент.

Скомпилируйте проект. В Android Studio это можно сделать через меню Build -> Make Project (CTRL+F9). После того как процесс завершится, класс DaggerAppComponent будет создан в недрах папки build\generated\. Студия теперь знает этот класс и должна предлагать добавить его в import, чтобы в коде не было никаких ошибок.

Чтобы добраться до компонента из MainActivity, мы можем сделать так:

После этого MainActivity сможет получать от компонента все необходимые объекты.

Нам остается рассказать компоненту, какие именно объекты мы хотим от него получать. Для этого мы будем наполнять его интерфейс методами. И вот тут у нас есть два вида методов.

Первый — это обычный и понятный get метод:

Т.е. мы просто описываем метод, который должен вернуть нужный нам объект. Когда даггер будет создавать класс-реализацию (DaggerAppComponent) этого интерфейса, он создаст в нем и реализацию метода getDatabaseHelper. Этот метод будет ходить в модуль StorageModule, создавать объект DatabaseHelper и возвращать его нам.

Второй вид методов посложнее для понимания. Это inject метод.

В этом случае мы не просим компонент создать и вернуть нам конкретный объект. Вместо этого мы просим компонент проверить какие объекты нужны в MainActivity. Компонент создаст эти объекты и передаст их сразу в MainActivity. Такая процедура называется инджект.

Рассмотрим оба способа подробнее.

Get метод

Нам от компонента нужны объекты DatabaseHelper и NetworkUtils. Для этого нам надо просто добавить в интерфейс компонента методы, которые будут возвращать эти объекты:

Создаем два метода. Они могут быть с любым именем, главное — это их возвращаемые типы (NetworkUtils и DatabaseHelper). Они дают понять компоненту, какие именно объекты мы хотим от него получать. При компиляции, даггер проверит, в каком модуле какой объект можно достать, и нагенерит в реализации двух этих методов соответствующий код создания этих объектов.

Список modules — это модули. Здесь нам надо указать модули, в которых компонент сможет найти код создания объектов. В StorageModule он найдет код для создания DatabaseHelper, а в NetworkModule — для NetworkUtils.

В MainActivity мы просто вызываем эти методы компонента, чтобы получить готовые объекты:

Если этот код у вас крэшит с NullPointerException, убедитесь, что добавили App класс в манифест.

Inject метод

У нас в MainActivity сейчас всего два объекта, которые мы получаем от компонента. Но если их будет штук 20, то придется в интерфейсе компонента описать 20 get-методов и в коде MainActivity написать 20 вызовов этих методов. У даггера есть более удобное решение для таких случаев. Мы можем научить компонент не возвращать объекты, а самому наполнять Activity требуемыми объектами. Т.е. мы даем компоненту экземпляр MainActivity, а он смотрит, какие объекты нужны, создает их и сам помещает в соответствующие поля.

Читайте также:  Сторонние лаунчеры для 10 андроида

Перепишем интерфейс компонента

Вместо пары get-методов мы описываем один inject-метод. Имя может быть любым, главное — это тип его единственного параметра. Мы указываем здесь MainActivity. Тем самым, мы говорим компоненту, что когда мы будем вызывать этот метод и передавать туда экземпляр MainActivity, мы ожидаем, что компонент наполнит этот экземпляр требуемыми объектами.

Аннотациями @Inject мы помечаем поля, которые компонент должен заполнить (инджектить). При вызове метода injectMainActivity компонент создаст объекты DatabaseHelper и NetworkUtils и поместит их в соответствующие поля MainActivity.

Этот механизм можно посмотреть в коде класса (DaggerAppComponent) компонента, который был сгенерирован даггером. Метод injectMainActivity, если поубирать все лишнее, выглядит примерно так:

Разумеется, get-методы и inject-методы могут быть использованы вместе в одном компоненте. Я описывал их отдельно друг от друга только для простоты понимания.

Где и как размещать все эти классы и интерфейсы зависит от вашей архитектуры и является отдельной темой для дискуссии.

Источник

Полный список

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

Урок обновлен 04.06.2017

На прошлом уроке мы установили среду разработки и Android SDK.

Теперь наконец-то мы можем создать наше первое приложение и посмотреть, как оно работает.

Чтобы создать приложение, нам нужно в Android Studio создать проект. При создании проекта, в нем создается модуль. В этом модуле мы рисуем экраны приложения и пишем код. И при запуске этого модуля мы получаем готовое приложение. Поэтому модуль по сути и является приложением. А проект — контейнер для модуля.

Т.е. в самом простом случае структура проекта такова:

Есть проект, и в нем есть модуль. При запуске проекта запускается модуль и мы получаем Android-приложение, которое создано в этом модуле.

В этом случае: один проект = одно Android-приложение (один модуль).

Но в одном проекте может быть несколько модулей. Да и проектов можно создать несколько.

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

При запуске какого-либо проекта необходимо будет указать, какой именно модуль вы хотите запустить. И каждый модуль является отдельным Android-приложением.

Т.е. в этом случае: один проект = несколько Android-приложений (несколько модулей).

Пока не будем вдаваться в детали, какая из предложенных схем лучше и удобнее. Для прохождения уроков можно создать один проект, и в нем создавать модули для каждого урока. Либо можно создавать отдельный проект, например, на каждые 10 уроков. Можно вообще создавать отдельный проект на каждый урок.

Я думаю, что мы начнем с варианта: один проект под все уроки. А со временем, как освоитесь, сами решите, какой вариант вам удобнее.

Давайте создадим проект. Открываем Android Studio. Ярлык для запуска должен быть в меню пуск. Либо вы можете открыть папку, куда устанавливали Android Studio на прошлом уроке. В подпапке bin должен быть EXE-файл.

Открылась среда разработки. Жмем Start a new Android Studio project.

Появилось окно создания проекта. Давайте заполнять.

Application name – имя проекта. Оно будет отображаться в списке проектов при открытии Android Studio. Напишем здесь Android lessons (т.е. Android уроки).

Company Domain – имя сайта, пишем startandroid.ru.

Package name – это понятие из Java, подробно можно посмотреть здесь. Вкратце – это префикс для имени классов нашего приложения. Как видите, пакет автоматически составился из имени сайта и имени проекта. Его всегда можно отредактировать вручную нажав на ссылку edit справа.

Project location – папка на компе, где будут находиться все файлы проекта. Мы на прошлом уроке создавали папку android, куда установили Android Studio и SDK. Там же создайте папку AndroidStudioProjects – в этой папке будем хранить все проекты Android Studio. И в ней создайте папку Androidlessons для нашего текущего проекта.

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

Визард спрашивает под какую платформу будем кодить и Minimum SDK (минимальная версия Android, на которой можно будет запустить приложение). Оставляем все как есть.

Визард может подгрузить необходимые ему компоненты.

Далее выберите Empty Activity.

Здесь ничего не меняем. Пока что нам нет необходимости знать, зачем все это нужно.

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

Если они вам не нужны, выключайте чекбокс.

Жмем Close.

Но снизу виден прогресс бар. Это означает, что еще выполняются какие то действия, и надо подождать.

И в итоге проект открывается

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

В левой части мы видим слово app – это модуль. По умолчанию при создании проекта создается модуль app. Нам он не интересен, т.к. мы будем создавать свои модули. Но пусть он остается, удалять его я вам не советую. Тот визард, который мы только что прошли при создании проекта, в основном касался как раз этого модуля.

Читайте также:  Как настроить триколор с помощью андроида

Итак, проект создан. Теперь создадим в проекте свой модуль. Повторюсь, что почти для каждого урока мы будем создавать модуль в этом проекте. Сейчас создадим модуль (приложение) для этого текущего урока. Эта процедура будет частично похожа на создание проекта, но с небольшими отличиями.

Чтобы создать модуль – в меню выбираем File -> New -> New module

Тип модуля выбираем Phone and Tablet Application

Application/Library name – непосредственно имя приложения, которое будет отображаться в списке приложений в смартфоне. Пишем тут FirstProject.

Module name – это название модуля. Т.е. это название будет отображаться слева в списке модулей, там, где сейчас есть app. Давайте придумаем шаблон для названия модулей.

На номер урока выделим три цифры, на номер проекта – одну. Также, будем добавлять название приложения — FirstProject. И все это напишем маленькими буквами и без пробелов. Получится такое имя модуля: p0031firstproject.

Package name – имя пакета отредактируем вручную, нажав edit справа. Оставим там ru.startandroid и добавим точку и имя модуля.

Minimum SDK оставляйте без изменений.

Далее выберите Empty Activity.

Здесь ничего не меняем

Жмем Finish и ждем.

Через какое-то время модуль будет создан и мы увидим его в списке слева. Это p0031firstproject — значение, которое мы указали в поле Module name.

Можно раскрыть этот модуль и посмотреть его содержимое.

Вкратце пройдемся по интересующим нас элементам

Файл AndroidManifest.xml – манифест или конфиг-файл приложения

В папке java и ее подпапках будет весь, написанный нами, код приложения

Папка res используется для файлов-ресурсов различного типа.

Все это мы будем в дальнейшем использовать, и станет понятнее, что и зачем нужно.

Давайте наконец-то запустим наше первое приложение! Для этого надо выбрать соответствующий ему модуль в выпадающем списке сверху

И жмем (чуть правее списка) кнопку с зеленым треугольником (либо комбинацию Shift+F10).

Чтобы запустить приложение, нужно какое-нить реальное Android-устройство или эмулятор.

У нас пока не на чем запускать приложение. Можете подключить шнуром реальное устройство, и оно здесь появится (если не возникнет проблем с драйверами или настройками устройства).

Либо можно создать эмулятор. Жмем Create New Virtual Device

Здесь можно выбрать форм-фактор устройства. Оставляйте то, что выбрано по умолчанию.

Жмем Next

Далее переходите на вкладку x86 Images и там должен быть образ, в названии которого нет слова Download. Т.е. он уже загружен и мы можем его использовать.

В данном случае на эмулятор будет установлен Android версии 7.1.1. Если вам нужна другая версия, то загружайте ее и используйте.

Далее нам предлагают указать название эмулятора и поменять его настройки. Оставляем все как есть

Жмем Finish

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

Жмем Ok

Через какое-то время (вплоть до нескольких минут) появится эмулятор

И в нем начнет запускаться Android

И в итоге запустится наше приложение

Название в заголовке — FirstProject. Именно его мы указывали при создании приложения.

Т.е. вы создали и запустили ваше первое приложение, с чем вас и поздравляю) Впереди сотни таких приложений и запусков.

Если эмулятор не показал ваше приложение, то убедитесь, что Android Studio «видит» этот эмулятор. Для этого снизу слева нажмите вкладку Android Monitor

И в списке устройств чуть выше должен быть виден эмулятор Nexus_5X_API_25

Если эмулятор есть в списке, а приложение не отобразилось, то попробуйте снова запустить приложение, нажав зеленый треугольник (Shift+F10).

Если эмулятора в списке нет, то закройте эмулятор и попробуйте снова запустить приложение.

Этот урок был обновлен в июне 2017. А многие последующие уроки были написаны аж в 2011-2012. Поэтому скриншоты в них могут отличаться от ваших. Это нормально.

Также, должен предупредить, что я делал и тестировал первые уроки под Android версии 2.3.3. Это указано в начале уроков. Но это вовсе не означает, что уроки уже безнадежно устарели и читать их смысла нет никакого. Код под 2.3.3 и 7.1.1 в подавляющем большинстве случаев абсолютно один и тот же. В новых версиях Android добавляются новые компоненты, а прошлые обычно остаются без изменений и достаточно редко меняются или объявляются устаревшими.

Если у вас открыт проект и вы хотите снова увидеть стартовое окно Android Studio, в меню выберите File > Close Project.

Вы увидите стартовое окно, слева будет список ваших проектов.

Если у вас имя пользователя русскими буквами, то могут возникнуть проблемы. Как их решить, можно прочесть на форуме в ветке этого урока.

Если строка выше не помогла, то попробуйте еще такое решение.

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

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Источник

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