привязка данных настраиваемого атрибута Kotlin

22

Я пытаюсь установить пользовательский атрибут, используя библиотеку Android DataBinding в моем проекте Kotlin:

Разметка

<ImageView
    android:id="@+id/imgView”
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_gravity="center"
    android:adjustViewBounds="true"
    app:imageUrl="@{segment.url}"/>

Код

  class Utils {
        companion object {
            @BindingAdapter("bind:imageUrl")
            @JvmStatic
            fun loadImage(view: ImageView, url:String) 
            {Picasso.with(view.context).load(url).error(R.drawable.error).into(view)}
    }       

Ошибка выполнения, которую я получаю:

  

A BindingAdapter in in не является статическим и требует использования объекта, извлеченного из DataBindingComponent. Если вы не используете метод инфляции, берущий DataBindingComponent, используйте DataBindingUtil.setDefaultComponent или сделайте все методы BindingAdapter статическими.

Любые указатели для его решения?

Это происходит только для пользовательских атрибутов. Остальные части данных работают нормально

    
задан Akshata 17.10.2016 в 13:53
источник

4 ответа

40

Просто держите функцию на верхнем уровне, не нужен класс или сопутствующий объект, он будет работать, поскольку функции верхнего уровня в Kotlin переведены на статические функции-члены класса с именем FileNameKt , если не переопределены @file:JvmName аннотации

@BindingAdapter("imageUrl")
fun loadImage(view: ImageView, url:String) { ... }

Еще один вариант заключается в том, чтобы аннотировать функцию расширения как @BindingAdapter , она будет работать, поскольку в сигнатуре байт-кода будет точно соответствовать сигнатурам, ожидаемым с помощью DataBindings (сгенерированный метод все равно примет объект расширенного класса в качестве первого аргумента), функция также должен оставаться на высшем уровне

@BindingAdapter("imageUrl")
fun ImageView.loadImage(url:String) { ... }
    
ответ дан Stepango 18.10.2016 в 06:40
источник
  • Спасибо! Работает как шарм :-) –  Akshata 19.10.2016 в 10:08
  • Этот ответ все еще дает мне ошибку. Ответ Ловиса работал на меня. –  omerjerk 19.09.2017 в 09:35
  • Что относительно лямбда? Как назначить лямбда-функцию в макете xml для пользовательского BindingAdapter в Kotlin? –  Владимир Широков 27.10.2017 в 10:17
  • @ ВладимирШироков да, вы можете, так же, как onClick работает для Views в XML, вам просто нужен правильный SAM-класс / интерфейс developer.android.com/reference/android/databinding/... –  Stepango 03.11.2017 в 09:41
  • @omerjerk не может быть правдой, проверьте свой код –  Stepango 03.11.2017 в 09:43
16

Попробуйте переключить порядок аннотаций. Кажется, проблема:

class Utils {
    companion object {
        @JvmStatic @BindingAdapter("imageUrl")
        fun loadImage(view: ImageView, url:String) { ... } 
    }
} 

Проблема заключается в том, что компилятор databindng использует getCompanion().loadImage иначе * .
Вы можете проверить это в сгенерированном классе com.your.package.databinding.*Binding

* Немного поиграв, я заметил, что это не имеет никакого отношения к порядку аннотаций, но кажется случайным. Кажется, он меняется, когда я нажимаю «rebuild». Это может быть ошибка в kapt или в компиляторе kotlin

    
ответ дан Lovis 17.10.2016 в 16:04
источник
  • То же самое здесь, изменение порядка не помогает. –  luca992 18.10.2016 в 00:40
  • Я поставил сообщение об ошибке kotlin на youtrack.jetbrains.com/issue/KT-14417 –  luca992 18.10.2016 в 01:24
  • Этот ответ сработал для меня. Благодаря! –  MidasLefko 28.06.2017 в 14:07
  • Связывание поиска статического метода и предоставление @JvmStatic внутри объекта-компаньона устраняет проблему –  Dharmendra Jadon 09.10.2017 в 08:00
1

Или используя расширение:

@BindingAdapter("imageUrl")
fun ImageView.setImageUrl(url: String?) {
    Picasso.with(context).load(url).into(this)
}

Теперь вы можете использовать эту функцию в любом месте

    
ответ дан Yazazzello 21.03.2018 в 21:22
источник
0

Добавление @JvmStatic до @BindingAdapter("imageUrl") исправлено моя проблема.

Для ex:

object BindingAdapters { @BindingAdapter("android:visibility") @JvmStatic fun setVisibility(view: View, visible: Boolean) { view.visibility = if (visible) View.VISIBLE else View.GONE } }     

ответ дан tieorange 04.01.2018 в 19:12
источник