Пробное Android-приложение на Kotlin

Пробный пример андроид приложения на Котлине

Никита


Здесь я вижу очень много граблей; на некоторых из них я танцевал больше года.

Безусловное создание фрагмента в Activity.onCreate

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)     // (1)
    setContentView(R.layout.activity_main)

    fragmentManager
            .beginTransaction()
            .replace(R.id.fragment, LoginFragment())
            .commit()                      // (2)
}

При первом старте Activity всё в порядке: в месте (2) создаётся и добавляется фрагмент. При рестартах после смены конфигурации (поворота экрана) фреймворк сам восстановит фрагмент в месте (1), после чего восстановленный фрагмент (там мог быть уже другой фрагмент, а за ним — сформированный действиями пользователя backstack) будет заменён новым в месте (2). Возникнет иллюзия, что состояние фрагмента не сохранилось. Нужно создавать фрагмент только при первом старте:

if (savedInstanceState == null) {
    fragmentManager
            .beginTransaction()
            .replace(R.id.fragment, LoginFragment())
            .commit()
}

Передача данных через static

val singleton = ProductSingleton
singleton.id = product.id
singleton.img = product.img
singleton.text = product.text
singleton.title = product.title
val intent = Intent(context, DetailProductActivity::class.java)
context.startActivity(intent)

Минусов у такого подхода полно.

Правильное решение — реализовать у передаваемого объекта интерфейс Parcelable (благо, в экспериментальном режиме работает @Parcelize) и передавать через extras.

Советы по работе с SharedPreferences

getDefaultSharedPreferences(context) отдаст SharedPreferences всего приложения. А, например, Activity.getPreferences(int) — префы для текущей Activity. Чтобы вообще не касаться API Android в этом шатком месте, я использую Kotpref.

Неотписка

Презентеры запускают асинхронщину (лезут в интернет), но не отменяют её, когда view уничтожается. Если запустить асинхронную операцию и уйти (повернуть экран, нажать Home или Back), можно получить state loss. Все асинхронные операции нужно отменять в onDestroyView.

Неправильное использование null-safety

override fun onBindViewHolder(holder: MyAdapter?, position: Int) {
    holder?.bindImage(products[position].img)
    holder?.bindText(products[position].text, products[position].text)
    holder?.bindOnClick(products[position], context)
}

Ой! Почему класс ViewHolder'а называется MyAdapter?

Именование

Хардкод

Странности

Вёрстка

Прочее