Pull to refresh
827.91
OTUS
Цифровые навыки от ведущих экспертов

16 советов по разработке для андроид на языке Kotlin. Часть 3

Reading time 4 min
Views 4.8K
И еще раз здравствуйте! В преддверии старта базового курса по Android-разработке, делимся заключительной частью статьи «16 советов по разработке для андроид на языке Kotlin».




Читать первую часть
Читать вторую часть

LATEINIT


Одной из ведущих особенностей Kotlin является его приверженность нулевой безопасности. Оператор lateinit предоставляет простой способ обеспечить нулевую безопасность и инициализировать переменную так, как этого требует Android. Эта функция прекрасна, тем не менее, к ней следует привыкнуть после работы на Java. Одна из идей заключается в том, что поле сразу объявляется с возможностью быть нулевым:

var total = 0 
var toolbar: Toolbar? = null


Эта языковая функция может вызвать сложности при работе с макетами Android, потому что мы не знаем как объявить представления, до того как макет объявлен, потому что неясно где они будут существовать, в Activity или Fragment. Это компенсируется при помощи дополнительных проверок на возможность нулевого значения в каждом месте, с которым мы взаимодействуем, но этот тот ещё геморрой. Поэтому лучше использовать модификатор lateinit:

lateinit var toolbar: Toolbar

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

@BindView(R.id.toolbar) lateinit var toolbar: Toolbar
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        ButterKnife.bind(this)
        // теперь можно без проблем обращаться к toolbar
        toolbar.setTitle("Hello There")
}

Безопасность типов


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

var feedFragment: FeedFragment? = supportFragmentManager
    .findFragmentByTag(TAG_FEED_FRAGMENT) as FeedFragment
но это может привести к сбою. Оператор as получит объект с нулевым значением, которое в данном случае исключено.
Правильный вариант такой:
var feedFragment: FeedFragment? = supportFragmentManager
    .findFragmentByTag(TAG_FEED_FRAGMENT) as? FeedFragment
if (feedFragment == null) {
    feedFragment = FeedFragment.newInstance()
    supportFragmentManager.beginTransaction()
            .replace(R.id.root_fragment, feedFragment, TAG_FEED_FRAGMENT)
            .commit()
}

LEVERAGING LET


Leveraging let позволяет вам выполнить блок, если значение объекта не равно нулю. Это позволяет вам избегать нулевых проверок и делает код более читабельным. В Java это выглядит так:

if (currentUser != null) {
    text.setText(currentUser.name)
}
А в Kotlin это выглядит так:
user?.let {
    println(it.name)
}

Этот код намного более удобный для чтения плюс автоматически создает переменную с ненулевым значением без опасности её обнуления.

SNULLOREMPTY | ISNULLORBLANK


Мы должны проверять поля много раз на протяжении разработки приложения для Android. Если вы справились с этим без использования Kotlin, возможно, вы знаете про класс TextUtils в Android. Класс TextUtils выглядит следующим образом:

if (TextUtils.isEmpty(name)) {
    // тут информируем пользователя
}

В этом примере вы можно заметить, что пользователь может установить в качестве имени пользователя даже просто пробелы, и он пройдет проверку. isNullOrEmpty и isNullOrBlank встроены в язык Kotlin, устраняют необходимость в TextUtils.isEmpty (someString) и обеспечивают дополнительное преимущество проверки только пробелов. Вы можете использовать при необходимости что-то типа такого:

// Если нам не важны пробелы в имени...
if (number.isNullOrEmpty()) {
// Просим пользователя ввести имя
}
//если пробелы критичны...
if (name.isNullOrBlank()) {
 // Просим пользователя ввести имя
}

Проверка правильности заполнения полей часто встречается при необходимости регистрации в приложении. Эти встроенные методы отлично подходят для проверки поля и оповещения пользователя, если что-то не так. Для более сложных проверок можно использовать методы расширения, например, для адресов электронной почты:

fun TextInputLayout.isValidForEmail(): Boolean {
    val input = editText?.text.toString()
    if (input.isNullOrBlank()) {
        error = resources.getString(R.string.required)
        return false
    } else if (emailPattern.matcher(input).matches()) {
        error = resources.getString(R.string.invalid_email)
        return false
    } else {
        error = null
        return true
    }
}

Советы для продвинутых


Вы знали, что для создания более чистого и лаконичного кода можете использовать лямбда-выражения?

Например, при работе в Java типично иметь простой класс прослушивателя, такой как:

public interface OnClickListener {  
    void onClick(View v);
}

Отличительной особенностью Kotlin является то, что он выполняет преобразования SAM (Single Abstract Method) для классов Java. Слухач кликов в Java, который выглядит как:

textView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // что-то делаем
    }
});
В Kotlin он может быть сокращён до:
textView.setOnClickListener { view ->
// что-то делаем
}

Как ни странно, такое преобразование невозможно для интерфейсов SAM, созданных в Kotlin. Это может удивить и даже немного разочаровать новых пользователей Kotlin. Если бы тот же самый интерфейс определен в Kotlin, слухач выглядит примерно так:

view.setOnClickListener(object : OnClickListener {
    override fun onClick(v: View?) {
       // что-то делаем
    }
})

Чтобы сократить такой код, можно записать своих слухачей в класс следующим образом:

private var onClickListener: ((View) -> Unit)? = null
fun setOnClickListener(listener: (view: View) -> Unit) {
    onClickListener = listener
}
// обращаемся у ним позже
onClickListener?.invoke(this)

Это вернет вас к простому лямбда-синтаксису, который делает возможным автоматическое преобразование SAM.

Заключение


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

На этом все. До встречи на курсе!
Tags:
Hubs:
+2
Comments 9
Comments Comments 9

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS