company_banner

Пишем на Kotlin под Android

    Года два назад я обнаружил, что в Android Market нет удобных мне приложений для учета времени, затраченного на разные проекты. Как настоящий лентяй, я решил не искать требуемое, а написать его сам. Это оказалось несколько сложнее, чем казалось вначале, и я все забросил в режиме вялотекущего хобби воплощение моего желания прожило больше года, медленно продвигаясь от идеи к альфа-версии.

    И тут вдруг добрые люди предложили мне рассказать, как писать под Android на Kotlin'e. Мне показалось, что это добрый знак, и я быстро переписал приложение на Kotlin, закончил его и выложил в Google Play.

    Важное уточнение: эта статья — только про то, как писать под Android на Kotlin'e. Интересно будет только тем, кто хочет попробовать Kotlin, и тем, кто хочет понять, зачем его пробовать. Приложение, которое я написал — очень-очень простое (и само по себе никак не относится к JetBrains). В его коде гарантированно можно что-то улучшить, оно выложено на Github только для примера, а не в качестве образца восхитительного кода. Оно работает, и если вам хочется его попробовать, то поставить можно отсюда. Но еще раз: это — демо, его цель — быть не совершенным приложением, а введением в Kotlin под Андроид.

    Опять что-то новое. И зачем мне это знать?




    Чтоб не оттягивать самое интересное, упомянем только самые главные преимущества Kotlin'a:
    • компактность кода. Быстро писать, легко читать, меньше наведенных ошибок;
    • встроенная защита от ошибок, прежде всего — nullability, т. е. требование к программисту явно указывать, что некая переменная может принимать значение null;
    • легкость в освоении (по-моему, даже начинающий разработчик на Java освоит Kotlin без труда).

    На Kotlin'e можно писать значительно быстрее, чем на Jav'e, и код, на мой взгляд, получается более красивым.

    Кстати, на github'e уже более 200 репозиториев с кодом на Kotlin'e, а если говорить про мобильные приложения, то Kotlin использовался при разработке мессенджера Telegram.

    Ну ладно, а с чего начать-то?


    Для работы потребуется IDE. Я по очевидным причинам предпочитаю IntelliJ IDEA, однако JetBrains делает плагин Kotlin и для Eclipse, а любители vim могут пользоваться отдельным компилятором языка.

    Дальше будем предполагать, что все, кто пожелает попробовать Kotlin в деле под Android, будут использовать IntelliJ IDEA. Для работы понадобится установить плагин Kotlin и позаботиться, чтобы на компьютере были gradle и Android SDK (это к Kotlin'y отношения не имеет, это надо для разработки под Android на чем угодно).

    Вначале была Java


    У меня уже было частично написанное приложение, когда я решил довести его до конца. Все было написано на Java.

    Суть приложения: на экране есть список красных задач, если кликнуть по задаче, она зеленеет, и время пошло: это значит, что пользователь работает над задачей. Как прекратил — кликает по ней еще раз, и задача снова краснеет, показывая, как немного времени он на нее потратил. Приложение слепо доверяет пользователю, не проверяя его никак: это вам не «большой брат смотрит за тобой» от oDesk'a.

    То, что было написано на Java, я хотел переписать на Kotlin, душа просила кода на 100% на Kotlin, несмотря на то, что в одном проекте можно использовать код на Java и на Kotlin'e одновременно. Оказалось, что с унаследованным кодом все просто: рядом с src/main/java создаем папку src/main/kotlin, и в нее помещаем классы. Файлы в Kotlin'е заканчиваются не на .java, а на .kt. Тут к месту оказался приятный момент: Kotlin не требует соответствия «один класс — один файл». Можно в один файл запихнуть столько классов, сколько хочется по логике приложения. В моем приложении было всего две логических части — работа с базой данных и экранный интерфейс пользователя, так что количество файлов можно было сократить.

    Плагин Kotlin к IntelliJ IDEA умеет конвертировать файлы .java в файлы .kt, выполняя аккуратную трансляцию из Java в Kotlin. Можно это делать через правый клик по файлу и контекстное меню, а можно — прямо при копировании кода на Java в файл .kt (плагин спросит, не сконвертировать ли).

    Пишем код на Kotlin'e


    Код на языке Kotlin компактен: например, класс вместе с конструктором и getters/setters описывается так:

    class Item (val project: String, var status: String, var secondsSpent: Long, var lastactivated: Long)
    


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

    Java:
    addButton.setOnClickListener(new OnClickListener() {
      public void onClick(View v) { 
        AlertDialog.Builder alert = new AlertDialog.Builder (this);
        alert.setPositiveButton("OK", new DialogInterface.OnClickListener()  {
           public void onClick(DialogInterface dialog, int which)  {
                result = input.getText().toString()
           }      
        });  
      }  
    } 
    


    Kotlin:
    addButton.setOnClickListener() {
          var alert = AlertDialog.Builder(this);
          alert.setPositiveButton("ОК") {
             dialog, whichButton ->  result = input.getText().toString()
          }
     }
    


    Согласитесь, код на Kotlin'e читается проще. Для внимательного читателя заметим, что это, конечно, только фрагмент кода, так как при создании диалога нужна не только кнопка «ОК», но и кнопка «Отмена». Полностью код выложен на Github.

    Что дает возможность так сокращать код? Например, в Kotlin'e возможна такая форма записи: если где-то в качестве параметра ожидается экземпляр класса с одним абстрактным методом, туда можно просто передать лямбду: именно это и показано в примере выше.

    Обратите внимание, что в Kotlin'e можно не указывать тип переменной, так как он будет выведен из правой части присваивания:

    Java Kotlin
    AlertDialog.Builder alert = new AlertDialog.Builder (this); val alert = AlertDialog.Builder(this)

    Интересная особенность синтаксиса в Kotlin'e: если в функцию передаются параметры, и последний параметр — функция, то ее можно вынести за скобки. Именно это мы видим во фрагменте, где в setPositiveButton передается лямбда, которая сработает по нажатию кнопки «ОК»:

    alert.setPositiveButton("ОК") { dialog, whichButton ->  result = input.getText().toString() }
    

    То же самое можно записать как

    alert.setPositiveButton("ОК", { dialog, whichButton ->  result = input.getText().toString() } )
    

    Вы вольны сами выбрать, какой вариант кажется проще для чтения.

    Использование библиотек на Java в коде на Kotlin'e

    Еще один приятный момент — возможность напрямую использовать библиотеки, написанные на Java, из кода на Kotlin.

    Например, чтобы нормально обрабатывать спецсимволы и Unicode в названиях проектов при сохранении их в SQLite, я использовал функции StringEscapeUtils.escapeJava и StringEscapeUtils.unescapeJava из популярной библиотеки, которую достаточно импортировать оператором import (и вписать в зависимости в свойствах проекта):

    import org.apache.commons.lang3.StringEscapeUtils
    

    Возвращаемое значение

    В Kotlin в функциональных литералах (a.k.a лямбда-функциях) запрещено использовать return, так как функциональный литерал возвращает значение, вычисленное в последнем выражении. Так, в вызове setOnTouchListener ожидается, что последний параметр вызова — функция, возвращающая boolean. Это значение фактически возвращает gestureDetector.onTouchEvent(aEvent).

    Java:
    gestureListener = new View.OnTouchListener() {
           public boolean onTouch(View v, MotionEvent event) {
                 return gestureDetector.onTouchEvent(event);
           }
    };
    

    Kotlin:
    getListView()?.setOnTouchListener() { v, aEvent -> gestureDetector.onTouchEvent(aEvent) }
    

    В коде функционального литерала на Kotlin нельзя писать return gestureDetector.onTouchEvent(aEvent), результат вызова gestureDetector.onTouchEvent(aEvent) и так будет возвращен.

    На самом деле есть специальные случаи, когда в функциональном литерале следует использовать нелокальный return. Если интересно, подробности есть в документации по Kotlin


    Аналогично работает возврат значений функциями, определенными через знак "=", вот так:

    override fun getCount() = data.size()
    

    Строковые шаблоны

    Чтобы избавиться от длинных строк, трудных для чтения и дающих неоптимальный байт-код, в Kotlin'e применены строковые шаблоны (string templates):

    setMessage("Удаляем $projectToDelete?")
    

    Здесь projectToDelete — это строковая переменная. Синтаксис такого шаблона привычен любому, кто имел дело с переменными среды в UNIX, например. Особенно удобны шаблоны для строк, составленных из текста и значений многих переменных, да еще и с форматированием:

    secondsSpent.setText("${format("%02d", hours)}:${format("%02d",minutes)}:${format("%02d", seconds)}")
    

    Между прочим, с форматированием по ходу дела вышла интересная история: тип String в Kotlin — свой, и метода format в нем нет, поэтому пришлось импортировать java.lang.String.format явным образом и потом к нему так обращаться. Удивительно, кстати, что ни в Java, ни в Kotlin'e до сих пор нет метода secondsToHumanReadableString, преобразующего целое число секунд в строку формата
    ЧЧ:ММ:СС.

    when и with

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

    with (alert) {
       setPositiveButton("ОК") {
          dialog, whichButton ->
          ... тут код обработчика нажатия ОК ...
       }
       setNegativeButton("Отмена") { dialog, whichButton -> }
    // по "Отмене" делать ничего и не надо
       create()
       show()
    }
    

    Без with получились бы alert.setPositiveButton, alert.setNegativeButton, alert.create, alert.show. When тоже повышает читаемость:

    when (item.status) {
       "active" -> {
       item.status = "inactive"
       ... тут еще всякие важные штуки ...
       }
       "inactive" -> {
       item.status = "active"
       ... тут еще тоже всякое ...
       }
    }
    

    Компиляция с помощью Gradle


    Если вы создаете build.gradle руками и/или собираете проект gradle'ом без IDE, то прочтите, как сдружить gradle, Kotlin и Android на сайте Kotlinlang.org.

    Не знаю, есть ли такая проблема у пользователей Android Studio, но у привычного к IntelliJ IDEA человека работа с Gradle может вызвать вопрос, как собрать .apk для релиза, а не для отладки.

    Для этого в IDEA есть плагин Gradle, открывается кликом по табу справа:



    По умолчанию IDEA собирает *-debug-unsigned.apk, т.е. то, что в Google Play не положишь. Чтобы оно стало *-release-signed.apk, надо сгенерировать ключ для подписи, положить его в keystore, и вписать несколько строк в build.gradle вашего проекта, чтобы Gradle знал, где ключ взять. Для сборки release, выберите в окне Gradle задачу assembleRelease двойным кликом по ней.

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

    На заметку


    Недавно открылся наш новый сайт про Kotlin kotlinlang.org, который хостится на Jekyll+Github. Чем это решение хорошо, на Хабре недавно уже писали.

    Если в статье какие-то примеры кода показались вам красивыми, то это — несомненная заслуга Натальи Ухорской, которая работает у нас в команде Kotlin. Я очень благодарен Наташе за советы, без которых эта статья оказалась бы короче, а код — менее похожим на классический Kotlin.

    Мы будем очень рады, если сэкономленные за счет использования Kotlin часы вы сможете провести на пляже. Хорошего остатка лета!

    UPD от 31.07.14, 18:55: поправлены некоторые термины и формулировки.
    Метки:
    JetBrains 87,43
    Компания
    Поделиться публикацией
    Похожие публикации
    Комментарии 39
    • +6
      Рад, что Kotlin развивается, спасибо за новости. Полгода назад пробовал писать на Kotlin под Android, возникла проблема с несколькими конструкторами для кастомных View: stackoverflow.com/questions/20670828/custom-android-views-with-kotlin

      Решена ли каким-то образом эта проблема на текущем этапе развития?
      • 0
        Тоже столкнулся с этой проблемой. Спасает то, что в таких случаях можно написать данный класс на Джаве и не париться. Но, конечно, было бы неплохо иметь поддержку нескольких конструкторов (хотя бы для обратной совместимости с Джавой).
      • –2
        А нет ли проблем у Kotlin с ART и Android L? Все-таки новый рантайм.
        • +3
          Насколько Я знаю, программа на языке Kotlin компилируется в *.class файлы для JVM. А затем Android SDK занимается преобразованием *.class в DEX для Android. То есть компилятору Kotlin всё равно, какая версия Android будет заниматься исполнением этого кода.
        • +1
          Спасибо за статью, приятно видеть что хороший язык уверенно идет вперед. Когда-то пытался прикрутить его к андроиду, тогда еще с Ant, сейчас вижу все стало еще проще с Gradle (http://zserge.com/blog/kotlin.html).

          Но честно скажу что тогда сильно не хватало документации.Вопрос может глупый, но скажите — а есть что-то типа JavaDocs по стандартным классам языка?

          А еще очень надоедало что почти все Android-классы приходилось писать со знаком вопроса, т.к. в java любой объект может быть null. Вопрос — планируется ли какая-нибудь обертка над Android SDK чтобы разработчикам не приходилось постоянно сталкиваться с java interoperability?

          Ну а в целом язык классный, молодцы!
          • 0
            Пару месяцев назад в Kotlin уже были аннотации для Android SDK, если мне не изменяет память.
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Отлично, то что надо! Спасибо.
              • +1
                Первой серьезной попыткой решить этот вопрос было написание kannotator-а который анализировал методы на предмет null-абельности и записывал эту информацию во внешние xml-аннотации, который kotlin-компилятор потом использовал. Но из за неудобства, как я слышал, от этого подхода решили отказаться, что придет им на замену я не знаю.
              • 0
                К слову об изначальной задаче — найти приложение для учета времени, затраченного на разные проекты.

                Тоже занялся этой задачей, и первое же найденное приложение меня вполне устроило — play.google.com/store/apps/details?id=com.toggl.timer
                • +11
                  Тут, по традиции, назойливый вопрос про С++ IDE
                  • +1
                    Это крайне забавный оффтопик, он есть во всех постах JetBrains и всегда в плюсе.
                    • 0
                      По традиции ответ — пока новостей нет. Мы очень хотим выпустить public EAP как можно быстрее. Но нам есть еще, над чем поработать (фидбека с приватного превью мы собрали уже достаточно). Особенно в плане перфоманса. Как будем сами удовлетворены результатом, так выпустим. Предположительно, это случится осенью. Точнее — пока не могу сказать.
                  • +1
                    На Kotlin я смотрел мельком — мне его рекомендовали как замену Scala, но при быстром взгляде преимуществ я не заметил.
                    Правильно я понимаю, что when — это pattern matching? На сколько полноценно он реализован? Есть ли вложенные патерны? Как описываются алгебраические типы данных?
                    • +1
                      В контексте Android преимущества есть: намного меньше стандартная библиотека.
                      • 0
                        ProGuard таки решает эту проблему.
                        • 0
                          Очень хорошо, если это действительно так, пару лет назад все было плохо, вся стандартная библиотека Scala dex'илась при каждой сборке :(
                      • +1
                        when — это не pattern matching. Скорее продвинутый switch из java. А with это вообще функция:
                        fun <T, R> with(receiver:T, f:T.()->R):R = receiver.f()
                        • 0
                          Ну pattern matching тоже в каком-то роде продвинутый switchю

                          with по этому коды я воспринял как локальный import в Scala. Теперь начинаю путаться… ;-)
                          T.()-> R — это ссылка на метод класса T? И этот метод генерируется при компиляции создании этой ссылки?
                          • +1
                            T.()-> R — это тип "extention function класса T. Т.е. можно передать функцию (лямбду), которая будет работать в контексте класса T как будто это его extension method. При компиляции, да, хотя наверное генерируется это не совсем то слово. Сделано для удобства работы в ide и всяких плюшек вроде билдеров, ну и во-первых, это красиво!
                        • +2
                          мне его рекомендовали как замену Scala, но при быстром взгляде преимуществ я не заметил
                          Два основных преимущества — в пороге вхождения и в читаемости кода «условным джуниором».
                          • –1
                            Понятно.
                            Это мне уже давно не важно :-).
                            • +1
                              Что, читаемость тоже? Вы пишете одноразовые проекты, которые никому не показываете?
                              • –2
                                Стараюсь, что бы те, кому я код показываю поскорее преставали быть юниорами.
                                • 0
                                  Эх. Чувствую, нарвусь. Есть такая старая шутка:
                                  — Почему Ubuntu?
                                  — Я не смог настроить Debian :(

                                  И по треду:
                                  — Почему Kotlin?
                                  — Я не смог выучить Scala :(
                        • 0
                          Дальше будем предполагать, что все, кто пожелает попробовать Kotlin в деле под Android, будут использовать IntelliJ IDEA. Для работы понадобится установить плагин Kotlin и позаботиться, чтобы на компьютере были gradle и Android SDK (это к Kotlin'y отношения не имеет, это надо для разработки под Android на чем угодно).


                          Попробовал слёту пощупать руками, хотя ни разу не java-программер и вообще не в этой теме.
                          Скачал себе под Windows XP (git и какие-то jre у меня уже были)
                          * download-cf.jetbrains.com/idea/ideaIC-13.1.4b.exe — последний IntelliJ IDEA Community edition
                          * dl.google.com/android/installer_r23.0.2-windows.exe — последний Android SDK
                          * downloads.gradle.org/distributions/gradle-2.0-all.zip — последний gradle

                          позапускал инсталляторы, в замеченном после этого дела Android SDK Manager повключал галочки у последних версий чего-то там, подтвердил согласие, и он долго чего-то там качал и ставил.

                          gradle распаковал виде папки C:\gradle-2.0

                          Пытался открыть проект из репозитория. Указал логин и путь на гитхабе, сказал давай в C:\Temp\ и оно скачало проект и спросило, чем и как импортировать проект.

                          Я сказал про Gradle, в окошке импорта проекта сказал что у меня локальный он есть, и получил сообщение, что нет экзешника C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 13.1.4\jre\bin\java.exe. Оказалось, что он лежит на уровень глубже, в C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 13.1.4\jre\jre\bin

                          Переложил всю начинку там уровнем выше, сочтя jre\jre\ ошибкой инсталлятора.

                          После этого gradle из-под IntelliJ завёлся, что-то долго делал, что-то докачивал кажись, а потом сказал

                          You are using an unsupported version of Gradle. Please use version 1.10.
                          Please point to a supported Gradle version in the project's Gradle settings or in the project's Gradle wrapper (if applicable.)

                          Consult IDE log for more details (Help | Show Log)

                          Кстати, до этого Help | Show Log не добраться, не открыв какого-нибудь проекта, хотя бы нового. Пришлось сделать, чтоб заглянуть. Этот пункт меню открыл мне папку C:\Documents and Settings\\.IdeaIC13\system\log

                          Я попробовал выбрать не локальную gradle, а customizable gradle wrapper, около которого что-то про gradle 1.7, и он попёр сам скачивать services.gradle.org/distributions/gradle-2.0-bin.zip

                          Результата не дождался, сам скачал 1.1 поменяв цифры в адресе, распаковал рядом с 2.0. Попробовал опять локальным дистрибутивом. Несколько раз он отваливался при скачке чего-то из maven.com, я повторял заход, надеясь, что он скачанное где-то кеширует.

                          В итоге облом — нужна не 1.1, а 1.10 (зря округлил, забыл что это не число)
                          Скачал 1.10. Она опять долго скачивала всякое, нужное проекту, и в итоге сказала так:

                          Could not read script 'C:\Temp\Kotime\kotime\signing.gradle' as it does not exist.

                          В общем, так пока ничего посмотреть не удалось. (
                          • +2
                            signing.gradle — это файл вот такого вида:
                            android {
                                ...
                                signingConfigs {
                                      release {
                                          storeFile file("release.keystore")
                                          storePassword "******"
                                          keyAlias "******"
                                          keyPassword "******"
                                     }
                                 }
                            }
                            

                            По очевидным причинам на github он не выложен, как и файл release.keystore. Как создать ключ для подписи и как положить его в файл release.keystore, как раз и написано по ссылке на stackoverflow в статье.
                          • 0
                            Да, собственно плагин Kotln я скачал и установил средствами самой IntelliJ, найдя его среди плагинов от JetBrains
                            • 0
                              При неустойчивом интернете, удручает неинформативное отображение прогресса скачивания этим customizable gradle wrapper файла services.gradle.org/distributions/gradle-2.0-bin.zip — непонятно, качает ли он, ждёт ли чего, умеет ли докачивать и ввобще, сколько осталось. Ползут диагональные полоски по вроде-бы полосе прогресса, и всё тут… понимай как хочешь. И нажатая отмена долго висит, прежде чем отмениться.
                              • 0
                                Спасибо за статью. Почти 2 года назад я попробовал писать одно приложение под android не на java. В результате ничего не вышло и пришлось все таки использовать ненавистную. Так вот одна из альтернатив была связка maven+kotlin(m5)+intellij но к сожалению ничего не вышло. Скажите а как сейчас обстоят дела в сфере дружбы kotlin и систем сборок при нацеливании на android? Скажите насколько вообще kotlin готов к продакшену?
                                • 0
                                  Отвечу как пользователь котлина с версии 0.1 и на java, и на js:
                                  сфере дружбы kotlin и систем сборок при нацеливании на android

                                  у меня вот не заладился простой проект с gradle, то есть проблемы решить можно, но не прямым путем и удовольствия мало. Да и плагин gradle в IDEA далек от совершенства.

                                  Учитывайте, что Котлин постоянно развивается, и что в production, что в своем проекте хранить компилятор/плагин нужно у себя под VCS, дабы избавить своих коллег или себя через n времени от ужаса «как же скомпилировать теперь именно той самой версией на момент последнего изменения кода».

                                  насколько вообще kotlin готов к продакшену?

                                  надо отметить, что такого удовольствия в написании кода в IDE как в случае java/typescript, не будет — довольно медленно оно работает (completion — в результате больше печатаешь, пока оно догоняет, inspections — довольно бедный набор и не всегда логичный).

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

                                  Ну а в runtme — если оно сразу не упало (компилятор может выдать байт-код некорректный в случае interop с существующим java кодом (такие проблемы редки, но пока что есть)), то проблем уже не будет.
                                  • 0
                                    из того, что я лично в этом проекте испытал: между версиями M7 и М8 появилось больше инспекций, при переходе на М8 всплыли кое-какие оплошности в моем старом коде.
                                • +2
                                  На правах рекламы хотел бы упомянуть генератор, который умеет создавать внутренний Kotlin DSL для UI (и не только) библиотек.

                                  Например, с помощью такого DSL интерфейс можно описывать следующим образом:

                                  // android
                                  scrollView {
                                       layoutParams(MATCH_PARENT, MATCH_PARENT)
                                  
                                       linearLayout {
                                          layoutParams(MATCH_PARENT, MATCH_PARENT)
                                          orientation = VERTICAL
                                  
                                          textView {
                                              linearLayoutParams(MATCH_PARENT, WRAP_CONTENT) {
                                                  bottomMargin = 15.dp
                                              }
                                              text = getString("description")
                                          }
                                      }    
                                  }
                                  

                                  // javafx
                                  gridPane {
                                      alignment = CENTER
                                      hgap = 10.0
                                      vgap = 10.0
                                      padding = Insets(25.0)
                                  
                                      text(column = 0, row = 0, colspan = 2, rowspan = 1) {
                                          text = "Welcome"
                                          font = Font.font("Tahoma", FontWeight.NORMAL, 20.0)
                                      }
                                  }
                                  

                                  Более крупные примеры можно посмотреть здесь.
                                  • 0
                                    Да это же практически Scaloid только круче и на Kotlin! Спасибо, добрый человек, отзывчивых вам пользователей и легких багфиксов!

                                    И сразу каверзный вопрос, а что с ActionBar, support классами и т.д? Потому что тот же скалоид застрял в этохе андроида 2.х без фрагментов.
                                    • 0
                                      Сперва в общих чертах опишу принцип работы генератора, а потом перейду непосредственно к ответам на вопросы.

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

                                      Немного раскрою термины и укажу примеры.

                                      Корень генерации — такой класс, для наследников которого, а также него самого должны быть созданы классы-аналоги (например, javafx.scene.Node).

                                      Отношение контейнер-объект — такая пара классов, что экземпляр одного класса можно «положить» в экземпляр другого (например, Node -> Pane в javafx).

                                      Билдер — функция, позволяющая за один вызов создать и настроить объект. Создается она с использованием таких фич языка, как именованные аргументы и параметры по умолчанию.

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

                                      Это я описал для лучшего понимания того, что вообще генератор делает.

                                      Теперь к вопросам. Пока эксперименты проводились только с классом View в качестве корня генерации, но другие классы тоже можно пробовать, метод такой:
                                      1) в корни добавляете интересующие классы
                                      2) запускаете генерацию
                                      3) компилируете сгенерированные исходники
                                      4) в коде получаете экземпляр класса Abc
                                      5а) либо передаете его в конструктор классу kotlin.dsl.Abc и настраиваете через свойства или with
                                      5б) либо с помощью функции ниже начинаете строить объект

                                      public fun Abc.dsl(init: kotlin.dsl.Abc.() -> Unit) {
                                          kotlin.dsl.Abc(this).init()
                                      }
                                      

                                      Пример:
                                      getActionBar().dsl {
                                          homeButtonEnabled = true
                                          ...
                                      }
                                      

                                      Вроде все должно получиться, и ActionBar, и support-классы, и фрагменты. Если что, пишите, будем разбираться :)
                                  • 0
                                    Удивительно, кстати, что ни в Java, ни в Kotlin'e до сих пор нет метода secondsToHumanReadableString, преобразующего целое число секунд в строку формата
                                    ЧЧ: ММ: СС.

                                    Для решения похожих задач есть библиотека Humanizer.jvm, правда желаемой автором поста функциональности там еще, вроде, нет. Прокт написан на Котлине, но может быть использован и в Java проекте.

                                    P.S. проект не мой.

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