Kotlin синтетичний в адаптері або ViewHolder


84

Я новачок у котліні. Я знайшов і намагався використовувати синтетичний метод замість надокучливого методу findViewByIdу своєму Activityкласі, але я виявив: "Якщо ми хочемо викликати синтетичні властивості в View (корисно в класах адаптерів), нам слід також імпортувати kotlinx.android.synthetic.main .view. *. " Але я не можу зрозуміти, як це точно працює? Є приклади?


Ви можете перевірити цей щоденник або цей приклад
Кабезас,

Відповіді:


96

Простий приклад з https://github.com/antoniolg/Kotlin-for-Android-Developers

import kotlinx.android.synthetic.item_forecast.view.*

class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        fun bindForecast(forecast: Forecast) {
            itemView.date.text = forecast.date.toDateString()
        }
    }
}

Не потрібно писати

val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()

Просто

itemView.date.text = forecast.date.toDateString()

Просто та ефективно!


4
гаразд, це може бути німим запитанням, але звідки береться посилання 'itemView'?
Сауло Агіар

4
Немає кешу для розширень подання, тому посилання на подання повинні бути кешовані, як у звичайному viewHolder.
Miha_x64

21
на жаль, це викликає findViewById при кожному виклику bind (): medium.com/proandroiddev/…
Мігель Белтран

2
@Mike, починаючи з Kotlin 1.1.4, усі подання будуть кешовані. Навіть у ViewHolders. У статті, яку ви опублікували, це також згадується.
Стефан Медак

2
@StefanMedack Я автор статті :) Хоча я повинен зазначити, що це лише частина експериментальних функцій і її потрібно активувати вручну. Я ще не пробував.
Мігель Белтран,

37

Котлінг 1.1.4 вихід

Додаткова інформація: https://antonioleiva.com/kotlin-android-extensions/

Вам потрібно активувати Kotlin Android Extentions, додавши це до вашого build.gradle:

apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
    experimental = true
}

Починаючи з цієї нової версії Kotlin, розширення Android включили деякі нові цікаві функції: кеші будь-якого класу (що цікаво включає ViewHolder)

Використання його на ViewHolder (або будь-якому власному класі). Зверніть увагу, що цей клас повинен реалізовувати LayoutContainerінтерфейс:

class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), 
        LayoutContainer {

    fun bind(title: String) {
        itemTitle.text = "Hello Kotlin!"
    }
}

3
Додавання до цієї інформації: Відповідно до Kotlin 1.1.4 ця функція експериментальна і її потрібно увімкнути у файлі build.gradle
Мігель Бельтран,

2
Це вже експериментально? Я хочу використовувати це у виробничому коді
Карсон Хольцхаймер

@CarsonHolzheimer ця функція все ще експериментальна
the_dani

здається, це навіть не працює 1.3.21. Я думаю, що вони не збираються це реалізовувати
user924

але ми можемо використати, containerView.itemTitle.text = "Hello Kotlin!"і я думаю, що цього досить
user924

11

Тобі потрібно

import kotlinx.android.synthetic.row_wall.view.*

А пізніше щось на зразок:

convertView.titleText.text = item.title

Справа в тому, що view. * Вводить розширення до класу View.


1
відповідь уже була надана stackoverflow.com/a/33428208/7767664 чому ви її повторили?
user924

8

Спробуйте

class CustomViewModel(val baseView: View) {
    val firstName = baseView.firstName
    val lastName = baseView.lastName
}

Об'єкт перегляду виставляє перегляди ref: https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890


відповідь уже була надана stackoverflow.com/a/33428208/7767664 чому ви її повторили?
user924

@ користувач924. якщо відповідь уже в іншому ланцюжку, будь ласка, модеруйте та позначте поточний ланцюжок як дублікат та додайте посилання на інший ланцюжок
гієна

4

Якщо ви використовуєте останню версію l;., Вам не потрібно додавати до неї експериментальний = true.

на рівні проекту Gradle

classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'

І на рівні програми Gradle

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.

і в залежностях ..

implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'

а імпорт нижче як

import kotlinx.android.synthetic.main.your_layout_file_name.view.*

і приклад

import kotlinx.android.synthetic.main.item_animal.view.*

class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {

    override fun bindData(animal: Animal) {
        itemView.tv_animal.text = animal.title
    }
}

де BaseViewHolder

abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
    LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
    abstract fun bindData(model: T)
}

Чи є офіційне підтвердження з цього приводу? Я вважаю, що використання .view.*цілей імпорту перетворює ціль, а запасний варіант буде findViewById<>кожного разу - саме той шаблон, який ViewHolderвідмовляє.
Skynet


1

Це означає, що ви повинні розмістити цей рядок на початку вихідного файлу:

import kotlinx.android.synthetic.main.view.*

Тож замість того, щоб, наприклад, findView(R.id.textView) as TextViewви писали просто textView. Останнє є синтетичним властивістю розширення, яке знаходиться в упаковціkotlinx.android.synthetic.main.view , тому вам доведеться імпортувати все з нього.

На офіційному сайті є підручник , погляньте.


1
Я це вже бачив. Я роблю це для своєї діяльності, як я описав вище. Але як я можу використовувати його всередині похідних BaseAdapter?
busylee

1
Ну, в основному ви можете викликати findViewById()метод на View, на зразок holder.findViewById(R.id.name). За допомогою Kotlin Android Extensions ви можете писати просто holder.name. Припустимо, цей код написаний всередині getView()функції:val base = inflater.inflate(R.layout.list_item, parent, false) base.name.text = "John Smith"
yanex

Але що, якщо мені доведеться використовувати кілька власників перегляду з різними макетами? Як я можу це реалізувати за допомогою синтетичного? Оскільки для кожного макета ми повинні використовувати конкретне «синтетичне посилання», і я маю кілька макетів з подібними ідентифікаторами.
Натан Рубінштейн,

0

FYI: прив'язка даних рекомендується замість синтетичної для перегляду перегляду.

Коментар від DA від Android від Google на Reddit

Гей! Адвокат розробника для Android у Google тут!

Я хотів додати трохи тла тут. Розширення Kotlin із синтетичними поглядами ніколи не було навмисно “рекомендованим”, хоча це не слід сприймати як рекомендацію не використовувати їх. Якщо вони працюють на вас, будь ласка, продовжуйте використовувати їх у своєму додатку!

Ми віддаляємось від них (наприклад, ми не навчаємо їх на курсі Udacity), тому що вони виставляють глобальний простір імен ідентифікаторів, який не пов’язаний із макетом, який насправді завищений без перевірок на недійсні пошуки, лише для Kotlin не викриває дозвільність, коли подання наявні лише в певній конфігурації. Разом із цими проблемами API збільшує кількість збоїв у роботі програм для Android.

З іншого боку, вони пропонують легкий API, який може спростити пошук подань. У цьому просторі також варто поглянути на прив'язку даних, яка також виконує автоматичні перегляди переглядів, а також інтегрується з LiveData для автоматичного оновлення переглядів при зміні даних.

Сьогодні в цьому просторі є кілька варіантів, які працюють:

Прив’язка даних - це рекомендація щодо пошуку подань, а також прив’язки, але це додає трохи накладних витрат у порівнянні з Android Kotlin Extensions. Варто поглянути, чи підходить це для вашого додатка. Прив’язка даних також дозволяє спостерігати за LiveData для автоматичного прив’язки подань при зміні даних. У порівнянні з Kotlin Extensions, він додає перевірку часу компіляції перегляду перегляду та безпеки типу. Розширення Android Kotlin офіційно не рекомендується (що не те саме, що рекомендація проти). Він поставляється із зазначеними вище проблемами, тому для нашого коду ми їх не використовуємо. Butter Knife - ще одне рішення, яке надзвичайно популярне і працює як для Kotlin, так і для мови програмування Java. Читання коментарів тут, там ' Багато розробників, яким пощастило з Kotlin Extensions. Це чудово - і те, про що ми матимемо на увазі, коли ми розглядаємо шляхи подальшого вдосконалення наших API. Якщо ви ще не заглянули в прив'язку даних, однозначно спробуйте.

Окрім того, наш внутрішній посібник зі стилю коду не призначений для безпосереднього застосування за межами нашої кодової бази. Наприклад, ми використовуємо mPrefixVariables, але немає жодної причини, щоб кожна програма мала дотримуватися цього стилю.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.