Функции расширения Kotlin

Есть ли возможность использовать функцию расширения с привязкой данных? XML:

<data>
    <import type="my.package.domain.country.model.City.streetName" />

    <variable
        name="city"
        type="my.package.domain.country.model.City" />
</data>

<TextView
    android:id="@+id/city"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{city.street.streetName()}" />

my.package.domain.country.model.city

data class City(
        val id: String,
        val street: Street
) 

fun City.streetName(): String = street.houseNumber

ошибка

[kapt] Возникла исключительная ситуация: android.databinding.tool.util.LoggedErrorException: обнаружены ошибки привязки данных. ****/ ошибка привязки данных ****msg: невозможно найти метод streetName() в классе my.package.domain.country.model.City

Спасибо;)

6 ответов

Вы должны сначала импортировать CityKt в XML

<import type="my.package.domain.country.model.CityKt" />

В разделе данных, то вы можете использовать его следующим образом

<TextView
  android:id="@+id/city"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@{CityKt.streetName(city)}" />

Если вы просмотрите CityKt, вы увидите, что есть статический метод Java с первым аргументом City

Хотя @skiff2011 верен, можно также использовать alias чтобы предотвратить Kt постфикс.

Например, некоторая функция расширения находится в ExtensionFunctionsKt может иметь псевдоним ExtensionFunctions

<import
    alias="ExtensionFunctions"
    type="com.helloworld.app.util.ExtensionFunctionsKt" />

<variable
    name="someData"
    type="com.helloworld.app.model.SomeData" />

В ExtensionFunctionпсевдоним теперь можно использовать для вызова функции расширения. Первым аргументом по-прежнему должна быть переменная расширенного класса.

<TextView
    android:id="@+id/city"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{ExtensionFunctions.doStuff(someData)}" />

Функция расширения

Бывший:

      fun Context.isDarkMode(): Boolean {

 }

Теперь у нас есть функция расширения для темного режима, к которой можно получить доступ через контекст.

Обычно в классе Kotlin мы можем получить доступ с помощью context obj, как показано ниже.

      context.isDarkMode()

Но в Xml мы не можем получить доступ, как указано выше.

Нам нужно импортировать функцию расширения, добавив KT к классу.

Пример. Если имя вашего файла - Extensions, то для импорта следует использовать ExtensionsKt.

Импортируйте, как показано ниже, в xml.

       <import type="com.paytmmoney.core.extensions.ExtensionsKt" />

И затем мы можем получить доступ к функции расширения, как показано ниже, т.е. нам нужно передать объект, для которого мы создаем расширение, то есть в нашем случае это контекст.

        app:context='@{(ExtensionsKt.isDarkMode(context)}'

Если вы используете класс Utils, вы можете:

       object Utils(){
       fun streetName(): String {}
}

<import
    type="com.helloworld.app.util.Utils" />



  <TextView
                android:id="@+id/txt" 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{Utils.INSTANCE.streetName()}"
              />

Используйте модель представления для вызова функций расширения.

Привязка данных использует псевдо-Java-код в XML, поэтому вы не можете использовать функции расширения. Вы можете указать их для kotlin, но для java их нужно вызывать, как сказано в разделе Вызов Kotlin из Java.

Шаги могут быть (я не пробовал):

<import type="my.package.domain.country.model.CityKt" />

...

<TextView
  android:id="@+id/city"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@{CityKt.streetName(city)}" />
Другие вопросы по тегам