
Перед прочтением этих советов вам желательно ознакомиться с документацией Kotlin и самостоятельно изучить язык на сайте
try.kotlinlang.org. Поскольку эти советы направлены именно на использование Kotlin в контексте разработки под Android, у вас также должен быть опыт работы с Android SDK. Также желательно ознакомиться с плагином Kotlin и использованием Kotlin с Android Studio от JetBrains (создателей Kotlin)
Описание объектов
Описания объектов допускают только синглетоны, которые нельзя принять за класс с возможностью создания экземпляров. Поэтому вам не нужно хранить синглеты как переменные статического класса или в классе Application.
Например, если у меня есть служебный класс со статическими методами, связанными с потоками, а я хочу получить доступ ко всему приложению, можно сделать вот так:
package com.myapps.example.util import android.os.Handler import android.os.Looper // помните, что это объект, а не класс object ThreadUtil { fun onMainThread(runnable: Runnable) { val mainHandler = Handler(Looper.getMainLooper()) mainHandler.post(runnable) } }
ThreadUtil можно вызвать позже таким же способом, как и при вызове метода статического класса:
ThreadUtil.onMainThread(runnable)
Это означает, что больше не нужно имитировать поведение статического класса при помощи закрытого конструктора и не нужно выяснять, где хранится экземпляр. Объекты, по сути, являются первоначальными элементами языка. По этому же принципу мы создаем объекты вместо внутренних классов:
iewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrollStateChanged(state: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageSelected(position: Int) { bindUser(position) } });
Оба по сути делают одно и то же — создают один экземпляр класса как объявленный объект.
Вспомогательные объекты
На первый взгляд в Kotlin нет статических переменных и методов. В данном языке отсутствуют эти концепции, зато есть концепция вспомогательных объектов. Они являются одноэлементными объектами в классе, содержащими методы и переменные, к которым вы можете обращаться статическим способом. Сопутствующий объект допускает определенные константы и методы, подобные статическим классам в Java. С его помощью вы можете следовать шаблону фрагментов newInstance.
Взгляните на сопутствующий объект в его простейшей форме:
class User { companion object { const val DEFAULT_USER_AGE = 30 } } // к нему можно обратиться позже так: user.age = User.DEFAULT_USER_AGE
В Android мы обычно используем статические методы и переменные для создания статических фабрик для фрагментов. Например:
class ViewUserActivity : AppCompatActivity() { companion object { const val KEY_USER = "user" fun intent(context: Context, user: User): Intent { val intent = Intent(context, ViewUserActivity::class.java) intent.putExtra(KEY_USER, user) return intent } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cooking) val user = intent.getParcelableExtra<User>(KEY_USER) //... } }
Создание Intent похоже на аналогичное действие в Java:
val intent = ViewUserActivity.intent(context, user) startActivity(intent)
Этот паттерн хорош, так как он уменьшает вероятность того, что у Intent или Fragment будут отсутствовать необходимые для отображения пользовательского или любого другого контента данные. Сопутствующие объекты — это способ сохранить форму статического доступа в Kotlin, и их следует использовать как компенсацию отсутствия классов.
Глобальные константы
Kotlin позволяет вам определять константы, которые видны в одном месте приложения (если это применимо). Но область действия констант по возможности должна быть максимально уменьшена. А в ситуациях, когда нужно, чтобы область была глобальной, в Kotlin есть отличный способ сделать это без необходимости использовать класс констант. Что-то типа:
package com.myapps.example import android.support.annotation.StringDef // Это не класс, это объект! const val PRESENTATION_MODE_PRESENTING = "presenting" const val PRESENTATION_MODE_EDITING = "editing"
Потом их можно использовать как константы в любом месте проекта:
import com.savvyapps.example.PRESENTATION_MODE_EDITING val currentPresentationMode = PRESENTATION_MODE_EDITING
Констант в проекте должно быть как можно меньше, чтобы уменьшить его сложность. Если у вас есть значение, которое относится только к пользовательскому классу, лучше поместить его во вспомогательный объект.
Расширения
Расширения полезны, потому что они позволяют добавлять функциональность класса, не наследуя его. Например, как добавить к Activity какой-нибудь метод, типа hideKeyboard()? С помощью расширений можно легко это сделать:
fun Activity.hideKeyboard(): Boolean { val view = currentFocus view?.let { val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager return inputMethodManager.hideSoftInputFromWindow(view.windowToken, InputMethodManager.HIDE_NOT_ALWAYS) } return false }
Расширения полезны тем, что они:
- помогают улучшить читабельность кода;
- избавляют от необходимости создавать служебные классы и методы.
Можно пойти дальше и улучшить архитектуру кода. Представьте, что у вас есть базовая модель, например, Article, которая рассматривается как класс данных, извлеченных из источника по API:
class Article(val title: String, val numberOfViews: Int, val topic: String)
Нужно определить релевантность Article для пользователя на основе какой-то формулы. Должны ли вы поместить её непосредственно в класс Article? И если модель должна содержать только данные из API, не более того, снова можно использовать расширения:
fun Article.isArticleRelevant(user: User): Boolean { return user.favoriteTopics.contains(topic) }
В настоящее время это простая возможность проверки присутствия темы Article в списке любимых тем пользователя.
Эта логика может меняться в зависимости от того, где вы хотите проверить эти и другие атрибуты пользовательского поведения. Поскольку эта логика поддерживается в некоторой степени независимо от модели Article, вы можете изменить ее в зависимости от цели, метода и его способности быть измененным.
ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/480534/
Добавить комментарий