- Уроки
- Урок 1. Введение.
- Урок 2. Установка Android Studio
- Урок 3. Создание AVD. Первое приложение. Структура Android-проекта.
- Урок 4. Компоненты экрана и их свойства
- Урок 5. Layout-файл в Activity. XML представление. Смена ориентации экрана.
- Урок 6. Виды Layouts. Ключевые отличия и свойства.
- Полный список
- Урок 1. Введение
- Зачем нужен Dagger
- Пример
- Теория
- Практика
- Подключение
- Объекты
- Модули
- Компонент
- Get метод
- Inject метод
Уроки
Урок 1. Введение.
Это урок-введение. Здесь мы пока ничего кодить не будем, я распишу причины, которые побудили меня создать этот сайт.
Урок 2. Установка Android Studio
Для того, чтобы писать программы — нужна среда разработки. В этом уроке мы подробно рассмотрим, как установить и настроить эту среду разработки.
Я буду описывать установку применимо к операционной системе Windows 7.
Урок 3. Создание AVD. Первое приложение. Структура Android-проекта.
Для того, чтобы тестировать приложения, нам понадобится Android Virtual Device (AVD). Это эмулятор Android-смартфона, на который мы сможем устанавливать созданные нами приложения, и запускать их там. Давайте его создадим.
Урок 4. Компоненты экрана и их свойства
Давайте посмотрим, как в Андроид приложениях формируется то, что мы видим на экране.
Урок 5. Layout-файл в Activity. XML представление. Смена ориентации экрана.
На прошлом уроке мы выяснили, что Activity читает layout-файл и отображает то, что в нем сконфигурировано. Теперь выясним, откуда Activity знает, какой именно layout-файл читать.
Урок 6. Виды Layouts. Ключевые отличия и свойства.
Расположение View-элементов на экране зависит от ViewGroup (Layout), в которой они находятся. В этом уроке мы рассмотрим основные виды Layout.
LinearLayout – отображает View-элементы в виде одной строки (если он Horizontal) или одного столбца (если он Vertical). Я использовал это на прошлом уроке, когда демонстрировал использование layout-файлов при смене ориентации.
TableLayout – отображает элементы в виде таблицы, по строкам и столбцам.
RelativeLayout – для каждого элемента настраивается его положение относительно других элементов.
AbsoluteLayout – для каждого элемента указывается явная позиция на экране в системе координат (x,y)
Источник
Полный список
Это урок-введение. Здесь мы пока ничего кодить не будем, я распишу причины, которые побудили меня создать этот сайт.
Я начал свое знакомство с разработкой под Android с примеров на официальном сайте. Половину того, чего делал — не понимал. Но какие-то знания оттуда вынес и немного почитал теории на том же ресурсе. На этом мое знакомство с Android завершилось ) Я не знал куда двигаться дальше. Про книги я почему-то не подумал, а зря …
Позже я наткнулся на статью «Five of the best Android development books». Интерес снова появился, стало понятно куда двигаться, я начал читать эти книги. Понял не все, но уже гораздо больше чем с первых примеров. Но если читать такие книги полностью с нуля, то многое будет не очевидно и непонятно.
Поэтому я хочу попытаться создать уроки по Android для начинающих, чтобы у читателя за спиной не оставалось непонятных ему тем. Я постараюсь максимально подробно все объяснять и делать различные примеры для большей наглядности. С каждым новым уроком буду вводить и использовать новые понятия и объекты, и использовать объекты из прошлых уроков для закрепления.
Каждый урок я стараюсь делать максимально независимым и обособленным, чтобы можно было зайти, посмотреть нужную тему и не просматривать кучу лишнего. Примеры стараюсь подбирать наиболее четко отображающие тему урока.
В отличие от некоторых авторов я не собираюсь научить вас программированию за «24 часа» или за «30 уроков». Мы все понимаем, что это невозможно ) Я не знаю, сколько у меня получится уроков. Думаю, что хватит около сотни, чтобы дать весь базис достаточно подробно. А потом еще сотня уйдет на различные продвинутые фишки. В общем тем, кто начинает изучать, скорее всего не придется много бегать по другим сайтам (кроме официального хелпа) за дополнительными знаниями. Здесь вы найдете много полезной, последовательной и изложенной простым языком информации.
Надо понимать, что мои уроки это не всегда руководство «как именно надо делать». Я могу чем-то пренебречь и что-то упустить, чтобы показать тему урока и не давать лишний материал. Поэтому прошу не считать все изложенное в уроках единственно правильным способом реализации.
Если у вас возникают проблемы с Android, то у сайта есть замечательный форум, который всегда рад помочь новичкам разобраться даже в самых простых вопросах. Правда, он защищен от спамеров контрольным вопросом и ответить на него, чтобы зарегиться, вы сможете только прочитав первые пять уроков. Это вынужденная защита. Зато, с момента введения этого вопроса, на форум не проник ни один спамер!
На данный момент уроки охватывают темы:
— создание экрана (в редакторе и программно)
— обработчики нажатия
— логи и всплывающие сообщения
— обычное меню, контекстное меню
— анимация View-компонентов
— создание и вызов Activity (+ возврат результата)
— Activity Lifecycle (состояния Activity)
— Intent, Intent Filter
— хранение данных (Preferences, SQLite)
— список и адаптеры
— диалоги
— Parcel, Parcelable
— Preferences при хранении настроек приложения
— работа с файлами
— Tab вкладки
— парсинг XML
— асинхронность (Handler, AsyncTask)
— сервисы
— Content Provider
— обработка касаний, мультитач
— фрагменты
— Action Bar, ActionMode
— виджеты
— ключи и подпись приложения
— ViewPager
— воспроизведение звука и видео
— запись звука
— работа с камерой
— сенсоры
— GPS
— Google Maps
— рисование
Я продолжаю читать книги и уроки будут появляться, пока я сам буду развиваться. В итоге, я думаю, мы придем к тому, что станем достаточно продвинутыми разработчиками, востребованными на рынке. В общем, как говорит один клоун из зомбоящика — «не переключайтесь» ) Будет интересно!
На следующем уроке мы установим и настроим среду разработки Android-приложений.
Разработка ведется на Java. Также могут понадобиться знания SQL, XML и прочих смежных технологий. Считается, что вы знакомы с ними. Если нет, то что-нибудь базисное по Java надо будет прочесть.
Гугл периодически выпускает обновления Android и для среды разработки. Поэтому вполне возможно, что содержимое урока немного устарело и реальная картинка отличается от скринов. Если это отличие кардинально или примеры не работают, пишите об этом на форуме в ветке урока. Будем актуализировать. Если же отличие только в цвете фона приложения или размере шрифта, то это, конечно, не критично и на посыл урока не влияет.
Также замечено, что поведение кода на разных версиях системы может быть различным. Я не проверял работоспособность материалов уроков на всех возможных версиях, поэтому ваши результаты могут отличаться от моих.
Иногда звучат высказывания, что большинство уроков сделаны для Android 2.3, а сейчас уже вышел Android версии, например, 100500 и уроки устарели. Один чудик как-то вообще написал, что уроки на 90% состоят из deprecated методов. Очень я не люблю комментировать чушь, но для начинающих я выскажу свое мнение по поводу этого всего дилетантства.
Я не могу с каждым выходом новой версии андроида переделывать все уроки. Тем более что, переделывать то ничего и не надо. Подавляющее большинство уроков останется прежними и все будет отлично работать на любой версии. К тому же доля устройств на Android 2.Х еще пока достаточно велика, чтобы ею пренебречь. И вы в ваших приложениях будете минимальную версию указывать 2.2 или 2.3, чтобы не потерять целый сегмент пользователей. Так что я не понимаю, в чем смысл кипиша.
Да, есть такое, что с выходом новых версий, некоторые уроки действительно кардинально устаревают и их надо обновлять. Это, например, коснулось Урока 52, и я сделал его обновление в отдельном уроке. Но постоянно отслеживать и обновлять целый урок из-за того, что там теперь один метод (о ужас-ужас. ) deprecated — это тяжко. Не забывайте, что я занимаюсь сайтом в свое свободное время. И я лучше потрачу его на написание новых материалов, чем на отслеживание и фикс устаревших методов.
Гуглохелп обычно для устаревших методов дает ссылку на новый метод. Так что если видите, что Eclipse ругается на устаревший метод, то просто ищете его в хелпе и смотрите, чем его заменили.
По Android Studio ситуация примерно та же. Не вижу смысла переходить на AS, т.к. главное в уроках — это код, а не среда разработки. Разве что, несколько первых уроков потом продублирую для AS
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Урок 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 |
Практика
Теперь на простом примере посмотрим, как создавать модули и компоненты, и как с их помощью 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, а он смотрит, какие объекты нужны, создает их и сам помещает в соответствующие поля.
Перепишем интерфейс компонента
Вместо пары get-методов мы описываем один inject-метод. Имя может быть любым, главное — это тип его единственного параметра. Мы указываем здесь MainActivity. Тем самым, мы говорим компоненту, что когда мы будем вызывать этот метод и передавать туда экземпляр MainActivity, мы ожидаем, что компонент наполнит этот экземпляр требуемыми объектами.
Аннотациями @Inject мы помечаем поля, которые компонент должен заполнить (инджектить). При вызове метода injectMainActivity компонент создаст объекты DatabaseHelper и NetworkUtils и поместит их в соответствующие поля MainActivity.
Этот механизм можно посмотреть в коде класса (DaggerAppComponent) компонента, который был сгенерирован даггером. Метод injectMainActivity, если поубирать все лишнее, выглядит примерно так:
Разумеется, get-методы и inject-методы могут быть использованы вместе в одном компоненте. Я описывал их отдельно друг от друга только для простоты понимания.
Где и как размещать все эти классы и интерфейсы зависит от вашей архитектуры и является отдельной темой для дискуссии.
Источник