готовые приложения для android studio kotlin

Современная Android разработка на Kotlin. Часть 1

Данная статья является перевом статьи от Mladen Rakonjac

Очень сложно найти один проект, который охватывал бы всё новое в разработке под Android в Android Studio 3.0, поэтому я решил написать его. В этой статье мы разберём следующее:

image loader

Каким будет наше приложение?

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

Я попытаюсь объяснить как можно больше строк кода. Вы всегда можете посмотреть код, который я опубликовал на GitHub.

Android Studio

Чтобы установить Android Studio 3, перейдите на эту страницу

Android Studio 3 поддерживает Kotlin. Откройте Create Android Project. Там вы увидите новый флажок с меткой Include Kotlin support. Он выбран по умолчанию. Дважды нажмите кнопку Далее и выберите Empty Activity, затем нажмите Finish.

Поздравляю! Вы сделали первое приложение для Android на Котлине :)

Kotlin

Вы можете видеть MainActivity.kt:

Расширение .kt означает, что файл является файлом Kotlin.

MainActivity: AppCompatActivity() означает, что мы расширяем AppCompatActivity.

Кроме того, все методы должны иметь ключевое слово fun и в Котлине вам не нужно использовать ;, но вы можете, если хотите. Вы должны использовать ключевое слово override, а не аннотацию, как в Java.

Так что же означает ? в savedInstanceState: Bundle?? Это означает, что savedInstanceState может быть типа Bundle или типа null. Kotlin null безопасный язык. Если у вас есть:

вы получите ошибку компиляции, потому что a должна быть инициализированна и это не может быть null. Это означает, что вы должны написать:

Кроме того, вы получите ошибку компиляции, если вы это сделаете:

Чтобы сделать a nullable, вы должны написать:

Почему эта важная особенность языка Котлина? Это помогает нам избежать NPE. Разработчики Android уже устали от NPE. Даже создатель null, сэр Тони Хоар, извинился за изобретение. Предположим, что мы имеем nullable nameTextView. Если переменная равна null, то в следующем коде мы получим NPE:

Но Котлин, на самом деле, хорош, он не позволят нам делать даже такое. Он заставляет нас использовать оператор ? или оператор !!. Если мы используем оператор ?:

Строка будет исполнена только если nameTextView не null. В ином случае, если вы используете оператор !!:

Мы получим NPE если nameTextView null. Это для авантюристов :).
Это было небольшое введение в Kotlin. Когда мы продолжим, я остановлюсь, чтобы описать другой специфический код на Котлине.

2. Build Variants

В разработке часто вы имеете различные окружения. Наиболее стандартным является тестовое и производственное окружение. Эти среды могут отличаться в URL-адресах сервера, иконке, имени, целевом API и т.д. На fleka в каждом проекте у вас есть:

В этом приложении мы будем использовать всех их. У них будут отличаться applicationId и имена. В gradle 3.0.0 есть новый API flavorDimension, который позволяет смешивать разновидности продукта, так, например, вы можете смешать разновидности demo и minApi23. В нашем приложении мы будем использовать только «default» flavorDimension. Перейдите в build.gradle для приложения и вставьте этот код внутри android <>

Перейдите в strings.xml и удалите строку app_name, чтобы у нас не было конфликтов. Затем нажмите Sync Now. Если вы перейдете в Build Variants, расположенным слева от экрана, вы увидите 4 варианта сборки, каждый из которых имеет два типа сборки: Debug и Release. Перейдите к варианту сборки demoProduction и запустите его. Затем переключитесь на другой и запустите его. Вы должны увидеть два приложения с разными именами.

image loader

3. ConstraintLayout

Если вы откроете activity_main.xml, вы увидите, что этот layout — ConstrainLayout. Если вы когда-либо писали приложение под iOS, вы знаете об AutoLayout. ConstraintLayout действительно похож на него. Они даже используют один и тот же алгоритм Cassowary.

Constraint помогает нам описать связи между View. Для каждого View у вас должно быть 4 Constraint, один для каждой стороны. В данном случае наш View ограничен родителем с каждой стороны.

Если вы передвинете TextView «Hello World» немного вверх во вкладке Design, во вкладке Text появится новая линия:

image loader

Вкладки Design и Text синхронизируются. Наши изменения во вкладке Design влияют на xml во вкладке Text и наоборот. Vertical_bias описывает вертикальную тенденцию view его Constraint. Если вы хотите центровать вертикально, используйте:

Давайте сделаем чтобы наш Activity показал только один репозиторий. В нём будут имя репозитория, количество звезд, владелец, и он будет показывать, есть ли у репозитория issues, или нет.

image loader

Чтобы получить такой layout, xml должен выглядеть так:

Пусть tools:text вас не смущает. Он просто помогает нам видеть хороший предварительный просмотр макета (layout’а).

Вы можете заметить, что наш макет плоский, ровный. Вложенных макетов нет. Вы должны использовать вложенные макеты как можно реже, поскольку это может повлиять на производительность. Более подробную информацию об этом вы можете найти здесь. Кроме того, ConstraintLayout отлично работает с разными размерами экрана:

image loader

и мне кажется, что я могу добиться желаемого результата очень быстро.
Это было небольшое введение в ConstraintLayout. Вы можете найти Google code lab здесь, и документацию о ConstraintLayout на GitHub.

4. Библиотека привязки данных Data Binding

Когда я услышал о библиотеке привязки данных, первое вопрос, который я задал себе: «ButterKnife работает очень хорошо для меня. Кроме того, я использую плагин, который помогает мне получать View из xml. Зачем мне это менять?». Как только я узнал больше о привязке данных, у меня было такое же чувство, какое у меня было, когда я впервые использовал ButterKnife.

Как ButterKnife помогает нам?

ButterKnife помогает нам избавиться от скучного findViewById. Итак, если у вас 5 View, без Butterknife у вас есть 5 + 5 строк, чтобы привязать ваши View. С ButterKnife у вас есть 5 строк. Вот и всё.

Что плохо в ButterKnife?

ButterKnife по-прежнему не решает проблему поддержки кода. Когда я использовал ButterKnife, я часто получал исключение во время выполнения, потому что я удалял View в xml, и не удалял код привязки в классе Activity / Fragment. Кроме того, если вы хотите добавить View в xml, вам нужно снова сделать привязку. Это очень скучно. Вы теряете время на поддерживание связей.

Что насчёт библиотеки привязки данных?

Есть много преимуществ! С помощью библиотеки привязки данных вы можете привязать свои View всего одной строкой кода! Позвольте мне показать вам, как это работает. Давайте добавим библиотеку Data Binding в наш проект:

Обратите внимание, что версия компилятора Data Binding должна совпадать с версией gradle в файле build.gradle проекта:

Нажмите Sync Now. Перейдите в activity_main.xml и оберните ConstraintLayout тегом layout:

Обратите внимание, что вам нужно переместить все xmlns в тег layout. Затем нажмите иконку Build или используйте сочетание клавиш Ctrl + F9 (Cmd + F9 на Mac). Нам нужно собрать проект, чтобы библиотека Data Binding могла сгенерировать класс ActivityMainBinding, который мы будем использовать в нашем классе MainActivity.

image loader

Если вы не выполните сборку проекта, вы не увидите класс ActivityMainBinding, потому что он генерируется во время компиляции. Мы все еще не закончили связывание, мы просто сказали, что у нас есть ненулевая переменная типа ActivityMainBinding. Кроме того, как вы можете заметить, я не указал ? в конце типа ActivityMainBinding, и я не инициализировал его. Как это возможно? Модификатор lateinit позволяет нам иметь ненулевые переменные, ожидающие инициализации. Подобно ButterKnife, инициализация привязки должна выполняться в методе onCreate, когда ваш Activity будет готов. Кроме того, вы не должны объявлять привязку в методе onCreate, потому что вы, вероятно, используете его вне области видимости метода onCreate. Наша привязка не должна быть нулевой, поэтому мы используем lateinit. Используя модификатор lateinit, нам не нужно проверять привязку переменной каждый раз, когда мы обращаемся к ней.

Давайте инициализируем нашу переменную binding. Вы должны заменить:

Вот и всё! Вы успешно привязали свои View. Теперь вы можете получить к ним доступ и применить изменения. Например, давайте изменим имя репозитория на «Modern Android Habrahabr Article»:

Как вы можете видеть, мы можем получить доступ ко всем View (у которых есть id, конечно) из activity_main.xml через переменную binding. Вот почему Data Binding лучше, чем ButterKnife.

Getter’ы и Setter’ы в Котлине

Возможно, вы уже заметили, что у нас нет метода .setText (), как в Java. Я хотел бы остановиться здесь, чтобы объяснить, как геттеры и сеттеры работают в Kotlin по сравнению с Java.

Во-первых, вы должны знать, почему мы используем сеттеры и геттеры. Мы используем их, чтобы скрыть переменные класса и разрешить доступ только с помощью методов, чтобы мы могли скрыть элементы класса от клиентов класса и запретить тем же клиентам напрямую изменять наш класс. Предположим, что у нас есть класс Square в Java:

Используя метод setA (), мы запрещаем клиентам класса устанавливать отрицательное значение стороне квадрата, оно не должно быть отрицательным. Используя этот подход, мы должны сделать a приватным, поэтому его нельзя установить напрямую. Это также означает, что клиент нашего класса не может получить a напрямую, поэтому мы должны предоставить getter. Этот getter возвращает a. Если у вас есть 10 переменных с аналогичными требованиями, вам необходимо предоставить 10 геттеров. Написание таких строк — это скучная вещь, в которой мы обычно не используем наш разум.

Kotlin облегчает жизнь нашего разработчика. Если вы вызываете

это не означает, что вы получаете доступ к a непосредственно. Это то же самое, что

в Java. Причина заключается в том, что Kotlin автоматически генерирует геттеры и сеттеры по умолчанию. В Котлине, вы должны указать специальный сеттер или геттер, только если он у вас есть. В противном случае, Kotlin автогенерирует его для вас:

field? Что это? Чтобы было ясно, давайте посмотрим на этот код:

Это означает, что вы вызываете метод set внутри метода set, потому что нет прямого доступа к свойству в мире Kotlin. Это создаст бесконечную рекурсию. Когда вы вызываете a = что-то, он автоматически вызывает метод set.
Надеюсь, теперь понятно, почему вы должны использовать ключевое слово field и как работают сеттеры и геттеры.

Вернемся к нашему коду. Я хотел бы показать вам ещё одну замечательную особенность языка Kotlin, apply:

apply позволяет вам вызывать несколько методов на одном экземпляре.

В Kotlin первичный конструктор является частью заголовка класса. Если вы не хотите предоставлять второй конструктор, это всё! Ваша работа по созданию класса завершена здесь. Нет параметров конструктора для назначений полей, нет геттеров и сеттеров. Целый класс в одной строке!

Вернитесь в класс MainActivity.kt и создайте экземпляр класса Repository:

Как вы можете заметить, для построения объекта не нужно ключевого слова new.

Теперь перейдем к activity_main.xml и добавим тег data:

Мы можем получить доступ к переменной repository, которая является типом Repository в нашем макете. Например, мы можем сделать следующее в TextView с идентификатором repository_name:

В TextView repository_name будет отображаться текст, полученный из свойства repositoryName переменной repository. Остается только связать переменную репозитория от xml до repository из MainActivity.kt.
Нажмите Build, чтобы сгенерировать библиотеку привязки данных для создания необходимых классов, вернитесь в MainActivity и добавить две строки:

Если вы запустите приложение, вы увидите, что в TextView появится «Habrahabr Android Repository Article». Хорошая функция, да? :)

Но что произойдёт, если мы сделаем следующее:

Отобразится ли новый текст через 2 секунды? Нет, не отобразится. Вы должны заново установить значение repository. Что-то вроде этого будет работать:

Но это скучно, если нужно будет делать это каждый раз, когда мы меняем какое-то свойство. Существует лучшее решение, называемое Property Observer.
Давайте сначала опишем, что такое паттерн Observer, нам понадобится это в разделе rxJava:

Возможно, вы уже слышали об androidweekly.net. Это еженедельный информационный бюллетень об Android разработке. Если вы хотите его получить, вам необходимо подписаться на него, указав свой адрес электронной почты. Позже, если вы захотите, вы можете остановить отказаться от подписки на своем сайте.

Это один из примеров паттерна Observer / Observable. В данном случае, Android Weekly — наблюдаемый (Observable), он выпускает информационные бюллетени каждую неделю. Читатели — это наблюдатели (Observers), они подписываются на него, ждут новых выпусков, и, как только они получают её, они читают её, и если некоторые из них решат, что им это не нравится, он / она может прекратить следить.

Property Observer, в нашем случае, представляет собой XML-макет, который будет прослушивать изменения в экземпляре Repository. Таким образом, Repository является наблюдаемым. Например, как только свойство name класса Repository изменяется в экземпляре класса, xml должен обновится без вызова:

Как сделать это с помощью библиотеки привязки данных? Библиотека привязки данных предоставляет нам класс BaseObservable, который должен быть реализован в классе Repository:

BR — это класс, который автоматически генерируется один раз, когда используется аннотация Bindable. Как вы можете видеть, как только новое значение установлено, мы узнаём об этом. Теперь вы можете запустить приложение, и вы увидите, что имя репозитория будет изменено через 2 секунды без повторного вызова функции executePendingBindings ().

Для этой части это всё. В следующей части я напишу о паттерне MVVM, паттерне Repository и об Android Wrapper Managers. Вы можете найти весь код здесь. Эта статья охватывает код до этого коммита.

Источник

Пишем MVP приложение на Kotlin под Android

image loader

Разработка приложений на Kotlin под Android набирает популярность среди разработчиков, однако статей в русскоязычном сегменте Интернета довольно мало. Я решил немного подправить ситуацию, и написать туториал по разработке приложения на Kotlin. Мы напишем полноценное приложение с использованием всех трендовых библиотек (кроме RxJava) в мире Android-разработки. В конце у нас должно получиться расширяемое и легко тестируемое приложение (сами тесты мы писать не будем).

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

Наверное, некоторые из вас знают, что помимо языка программирования Kotlin JetBrains также разрабатывает библиотеку Anko, для создания UI приложения, в качестве замены обычным XML-файлам. Мы не будем использовать его в нашем проекте, дабы не ставить в затруднительное положение людей не знакомых с Anko.

Настройка Android Studio

Для написания приложений на языке Kotlin, Android Studio нужен специальный плагин. Инструкцию по установке плагина можно найти здесь. Также не забудьте отключить функцию «Instant Run» в настройках Android Studio, т. к. на данный момент она не поддерживается плагином Kotlin.

Для корректной работы генерации кода нужно использовать версию плагина не ниже 1.0.1. Я использовал версию Kotlin 1.0.2 EAP. Вот так выглядит файл build.gradle приложения в моем проекте:

Что будем писать?

Итак, для начала нам нужно определиться что же мы будем писать? Недолго думая я остановился на приложении-заметках. Название тоже придумалось легко — Notelin. Приложение очень простое и состоит из двух экранов:

— Главный экран — содержит в себе список с заметками
— Экран заметки — здесь можно смотреть/редактировать содержание выбранной заметки

Требования к приложению небольшие:

— Добавление/просмотр/удаление заметки
— Просмотр информации о заметке
— Сортировка заметок по заголовку и по дате
— Поиск по заголовкам заметок

Используемые библиотеки

Для работы с базой данных я буду использовать библиотеку Android Active. Урок по работе с ней можно найти по этой ссылке. Для реализации Depency Injection была использована библиотека Dagger 2. На Хабре есть много статей по работе с ней. Основой всего приложения будет библиотека Moxy. С ее помощью мы реализуем паттерн MVP в нашем проекте. Она полностью решает проблемы жизненного цикла, благодаря чему вы можете не переживать о пересоздании компонентов вашего приложения. Также мы воспользуемся набором расширений для языка Kotlin в Android — KAndroid. Про остальные библиотеки я буду рассказывать по ходу дела.

Ниже приведен список зависимостей проекта:

А вот так выглядит список зависимостей приложения:

Обратите внимание, что вместо apt я использую kapt. Это плагин для Gradle, позволяющий аннотировать Kotlin-элементы.

Структура приложения

Вот так выглядит структура нашего проекта в конечном варианте:

image loader

Создаем Model

У заметок будет четыре поля:

Реализуем все это в коде:

По этой модели библиотекой ActiveAndroid будет создана БД, в которой будут храниться наши заметки. Если вы заметили, у нас есть два конструктора: пустой и с параметрами. Первый конструктор будем использовать мы, а второй — ActiveAndroid. Наша модель наследуется от класса Model, благодаря чему мы можем сохранять и удалять наши заметки просто вызывая методы save() и delete(), например:

Но прежде чем использовать нашу модель, нам нужно прописать кое-какие мета-данные в Manifest-файле:

Думаю, все понятно без комментариев. Осталось унаследовать класс Application от com.activeandroid.app.Application:

Чтобы приложение было менее зависимо от БД я создал обертку NoteDao над нашей моделью, в которой будут происходить все операции по созданию, сохранению, обновлению и удалению заметок:

Наверное, вы заметили, что для создания объектов мы не использовали ключевое слово new — это отличие Kotlin от Java.

Экран с заметками

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

Создаем MainView и MainPresenter

image loader

Теперь нам нужно перевести все это в код. Для начала создадим интерфейс нашей View:

Далее мы реализуем созданный интерфейс в нашей активити:

Одной из особенностей Kotlin, является то, что наследование и реализация интерфейсов указывается через двоеточие после имени класса. Также не имеет разницы идет название родительского класса перед интерфейсами, после или даже между ними, главное, чтобы класс в списке был один. Т. е. запись выше могла бы выглядеть так:

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

Пока оставим методы пустыми. Как видите, активити наследуется от MvpAppCompatActivity. Это нужно для того, чтобы активити могла восстанавливать состояние при повороте экрана.

Создадим класс презентер:

Презентер также наследуется от MvpPresenter, которому мы указываем с какой View мы будем работать.Осталось инжектировать нашу модель в презентер. Для этого мы создаем модуль — поставщика NoteDao:

Создадим Component для инжектирования презентера:

Теперь нам нужно создать статический экземпляр класса AppComponent в классе Application:

Теперь мы можем инжектировать нашу модель в презентере:

Для взаимодействия MainView и MainPresenter нам нужно создать переменную в MainActivity:

Плагин Moxy сам привяжет View к фрагменту и произведет другие необходимые действия.

Создадим разметку экрана со списком и плавающей кнопкой. Файл activity_main.xml:

Для реализации летающей кнопки я использовал библиотеку FloatingActionButton. Google уже добавили FAB в support-библиотеку, поэтому вы можете воспользоваться их решением.

Укажем нашей Activity, какой макет она должна показывать:

Далее нам нужно связать FAB и список, чтобы при прокручивании списка вверх кнопка исчезала:

Нам не нужно писать порядком надоевший findViewById, нужно лишь прописать одну строчку в блоке с import’ами:

Как видите, последний пакет совпадает с названием нашего xml-файла. IDE автоматически инициализирует свойства (property) наших View и их имена совпадают с ID, которые мы указали в разметке.

Давайте реализуем загрузку заметок из БД. Заметки нужно загружать только один раз и использовать их в последующем. В этом нам поможет метод onFirstViewAttach класса MvpPresenter, который вызывается единожды при первой привязке View к презентеру. Далее, сколько бы мы не крутили и вертели нашу Activity, данные будут закешированы в презентере.

Создадим адаптер для нашего списка:

В адаптере мы используем метод formatDate. Он служит для форматирования даты в строку:

Данный метод находится в файле DateUtils.kt и мы можем использовать как обычный статический метод. Отличие от статического метода здесь в том, что метод принадлежит не классу, а пакету и нам не нужно писать имя класса перед названием метода. В аннотации мы указываем название класса, через который мы будем обращаться к методу из Java. Например в Java дынный метод будет вызываться так:

В методе onNotesLoaded нашей Activity мы показываем наши заметки:

Если заметок нет, то мы показываем сообщение «Нет заметок» в TextView.

Насколько я знаю, для обработки клика по элементам RecycleView не существует «официального» OnItemClickListener. Поэтому мы воспользуемся своим решением:

В методе onCreate нашей Activity пишем:

Функция with позволяет не писать каждый раз имя переменной, а только лишь вызывать методы у объекта, который мы передали в нее. Обратите внимание, что для получения Activity я использовал не просто this, а this@MainActivity. Это связано с тем, что при использовании this в блоке with, возвращается объект, который мы передали в функцию with. При обычном клике по пункту мы переходим на Activity, где мы можем просмотреть текст нашей заметки. При долгом нажатии появляется контекстное меню. Если вы заметили, перед закрывающей скобкой я не написал слово return. Это не ошибка, а особенность языка Kotlin.

Вот что происходит при нажатии на пункт меню в презентере:

Мы еще не создали класс NoteActivity, поэтому компилятор будет выдавать ошибку. Для решения этой проблемы можно создать класс NoteActivity или вовсе закомментировать код внутри метода openNote. Запись NoteActivity::class.java аналогична NoteActivity.class в Java. Также заметьте, что мы обращаемся к списку не через метод get(position), а через квадратные скобки, как к обычному массиву.

При использовании MVP-библиотеки Moxy в своем приложении, нам нужно привыкать, что все действия с View, такие как показ/закрытие диалога и другие, должны проходить через презентер. Изначально это не очень привычно и неудобно, но пользы от этого гораздо больше, т. к. мы можем быть уверены, что при пересоздании Activity наше диалоговое окно никуда не пропадет.

Я не буду показывать код контекстного меню, удаления и показа информации о заметке т. к. статья получается очень большой. Но, думаю, общий смысл вы уловили. Также следует отметить, что метод hideNoteContextDialog у презентера должен вызываться даже при закрытии диалога через кнопку назад или при нажатии на область за границами диалога.

При нажатии на FAB должна создаваться новая заметка:

Для создания новой заметки мы вызываем у презентера функция openNewNote:

Метод openNewNote использует созданный нами ранее openNote, в который мы передаем Context и позицию заметки в списке.

Реализуем поиск по заметкам

image loader

Давайте добавим поиск по заметкам. Создайте в папке res/menu файл main.xml:

В MainActivity пишем:

При изменении текста в поле поиска мы передаем строку из поля в презентер, после чего показываем результаты в списке. На самом деле, у SearchView нет метода onQueryChange, его добавила библиотека KAndroid.

Реализуем поиск в презентере:

Обратите внимание, как красиво, в одну строчку мы реализовали поиск по списку с помощью метода filter и лямбд. В Java тот же функционал занял бы 6-7строк. Осталось отобразить результаты поиска:

Реализуем сортировку заметок

И последний этап в создании главного экрана, это сортировка заметок. Добавим в res/menu/main.xml следующие строки:

Теперь нам нужно обработать нажатие на пункты меню:

Оператор when является более функциональным аналогом switch-case в Java. Код сортировки в MainPresenter:

Экран с содержанием заметки

Теперь нам нужно создать экран с содержанием заметки. Здесь пользователь может просмотреть/отредактировать заголовок и текст заметки, сохранить или удалить ее, а также просмотреть информацию о заметке.

Создаем NoteView и NotePresenter

image loader

Экран содержит всего лишь три View:

-Заголовок
-Дата последнего изменения
-Текст заметки

А вот и сама разметка:

В начале статьи я мельком упомянул об Anko. Библиотека позволяет существенно сократить код, не теряя при этом в удобочитаемости. Вот так, например, выглядела бы наша разметка при использовании Anko:

Но не будем отвлекаться и приступим к написанию кода. Первым делом нам нужно создать View:

Имплементируем NoteView в NoteActivity:

В onCreate мы извлекаем id заметки, чтобы презентер достал заметку из БД и передал данные во View. Создадим презентер:

Не забудьте добавить в класс AppComponent строку:

Покажем нашу заметку:

Реализуем сохранение заметки

Для сохранения заметки нам нужно выбрать соответствующий пункт в меню. Создайте файл res/menu/note.xml:

Опять же, я не стал приводить код удаления и вывода информации о заметке. При просмотре исходного кода, вы можете заметить, что помимо идентификатора заметки я передал в NoteActivity позицию заметки в списке. Это нужно для того, чтобы при удалении заметки на экране просмотра заметки, она также удалялась из списка. Для реализации этого функционала я использовал EventBus. И опять, я не стал приводить код.

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

Благодарности

Конечно же, нельзя забывать о людях, которые помогли мне при написании статьи. Хотел бы выразить благодарность хабраюзерам Юрию Шмакову (@senneco) за помощь с его библиотекой Moxy и за помощь по другим вопросам. Также, хочу сказать спаcибо сотруднику JetBrains Роману Белову (@belovrv) за ревью статьи и за предоставленный код на Anko.

UPD: Еще хотел сказать спасибо Sirikid за EPIC COMMIT, благодаря которому я переделал внушительную часть кода с использованием фич Kotlin’а.

Заключение

Надеюсь, эта статья смогла убедить вас в том, что писать приложения на Kotlin не трудно, а может даже и легче, чем на Java. Конечно же, могут встречаться и баги, которые сотрудники JetBrains достаточно быстро фиксят. Если у вас появились какие-либо вопросы, вы можете задать их напрямую разработчикам на Slack-канале. Также вы можете почитать статьи о разработке на Kotlin здесь.

Источник

Понравилась статья? Поделить с друзьями:
Добавить комментарий
  • Как сделать успешный бизнес на ритуальных услугах
  • Выездной кейтеринг в России
  • Риски бизнеса: без чего не обойтись на пути к успеху
  • готовые ооо с расчетным счетом и директором в москве дешево
  • готовые ооо с расчетным счетом евро трек