Pull to refresh

Comments 22

Слежу за этим проектом с раннего этапа, еще когда он именовался koan) Имел каверзную дисскусию с автором, было интересно.
И опять какая-то незримая фея сыплет пыльцу, на мою карму :)
Насчет последнего, или пример не удачный но мне не кажется что IllegalStateException будет чем-то принципиально отличаться от NPE. Может этот делагат можно использовать как монаду?
Вы не совсем правильно поняли. Конструкция
by Delegates.notNull()
нужна чтобы поле mHelloWorldTextView имело тип TextView, а не TextView?, чтобы не было всяких операторов типа "?." и "!!.".

Для справки (на всякий случай) — объект типа TextView не может принимать значение null. Для null есть типы с "?" в конце — TextView?.. Это во всем котлине. Если объект имеет тип "?", то к его полям нельзя обращаться непосредственно через "." — код просто не скомпилируется. Для этого есть операторы "?." и "!!." (сложно представить, как можно было додуматься до такого оператора:))
Я к тому что по моему опыту textView в Activity, в 90% случаев имеет null значение не потому что ему намерено null присвоили, а потому что забыли инициализировать в onCreate(). И тут Delegates.notNull() ни разу не помощник получается. Потому и говорю про не самый удачный пример.
Опять-таки дело не в этом. Я не зря привел такой пример:
private var mHelloWorldTextView : TextView = //???

Переменную mHelloWorldTextView нужно чем-то инициализировать. А в данном случае (без Delegates) можно инициализировать только null. Тогда тип mHelloWorldTextView уже будет не TextView, а TextView?, что не хочется.
Пример предназначен только для этого.

Впрочем, Kotlin Android Extensions решает все проблемы.
Гораздо лучше сделать вот так:

private val mHelloWorldTextView : TextView by Delegates.lazy { findViewById(R.id.helloWorldTextView) as TextView }

Во фрагментах так просто не получится, но в активити самое то.
Да, это очень сильная вещь, я забыл упомянуть о ней.
К сожалению, подход не универсальный и не приводит у уменьшению кода, по факту это тоже самое, что и установить поле руками (ну возможна небольшая экономия на ленивой инициализации).
А что как kotlin для андроид сосуществует с DI типа roboguice или dagger? Слышал что теряется совместимость. Может есть какие-то свои альтернативы?
>из тех, кто интересуется разработкой под Android, только ленивый не слышал про Kotlin
О, наконец-то я достоверно выяснил, что я ленив :)
День открытий (-:
Я тоже не слышал (-:
У меня несколько вопросов по Anko DSL.
Как применять стили?
Как использовать custom views?
Есть ли удобный способ брать размеры элеметов из dimen.xml?
Что делать если понадобится 2 разметки для portrait и landscape?
Хорошие вопросы)
Во-первых, замечу еще такую вещь, что при открытии файла xml разметки во вкладке Code есть возможность конвертации в Koan DSL. Однако работает пока далеко не очень)

Теперь по вопросам:
1) Насколько я знаю, стили, описанные в xml, использовать нельзя. Это в принципе логично, все пишем в DSL (однако с dimen такое не катит, под разные размеры экрана придется в xml писать).
В общем, можно это делать с помощью функции style. Если стили где-то храним, то делаем примерно такое:
private fun editTextStyle(editText: EditText) {
    editText.textSize = 18f
    editText.textColor = Color.RED
}

//=>

relativeLayout {
    editText {
        style { editTextStyle(this) }
    }.layoutParams { centerInParent(); }
}


2) Custom view — легко, нужно просто знать. Пишем такую функцию (допустим, класс называется MyView):
fun ViewManager.myView(init: MyView.() -> Unit = {}) =
        __dslAddView({ MyView(it) }, init, this)

И можем спокойно использовать:
relativeLayout {
    myView {
        //...
    }
}


3) Еще проще:
val size = dip(getResources().getDimension(R.dimen.my_dimen))


4) Тоже достаточно просто, создаем две разметки и в рантайме проверяем, какая ориентация:
private fun portrait() {
    linearLayout {
    }
}
    
private fun landscape() {
    relativeLayout {
    }
}

//=>

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
    landscape()
}
else {
    portrait()
}
Спасибо! Ребота со стилями и dimen не выглядит очень удобной, учитывая что использовать сушествующие стили например из Sapport Library — совсем не тривиально. На мой взгляд весь смысл описания UI в XML это отделение разметки от кода, а в Anko объединение разметки и кода описывается как приемущество что довольно странно на мой взгляд. И еще один вопрос у меня назрел. Как в Anko можно переиспользовать разметку(аналоги layout и merge тегов)?
Да, есть такой момент. Впрочем, все это может быть переработано еще)
Насчет переиспользования есть кое-что — сам не пробовал, но похоже. Это с xml, а с DSL — создаем функции, которые будут возвращать часть UI (например, поле ввода с кнопкой) один раз и используем везде.
1) Можно так подсунуть

    <style name="TxtStyle" parent="Theme.AppCompat.Light">
        <item name="android:textSize">18dp</item>
        <item name="android:textColor">#ff0000</item>
    </style>

relativeLayout {
    ankoView({ TextView(ContextThemeWrapper(ctx, R.style.TxtStyle)) }) {

    }.layoutParams { centerInParent(); }
}
Sign up to leave a comment.

Articles