Kotlin DataBinding pass static function into layou

2019-06-28 01:18发布

问题:

In Java, i can easily pass static function to layout xml using:

public static String formatUnixTime(long timeInSeconds, String pattern) {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, Locale.US);
    String value = simpleDateFormat.format(new Date(timeInSeconds * 1000));

    return value;
}

in xml:

android:text='@{Utils.formatUnixTime(model.start_time, "hh:mm:ss")}'

But i tried in Kotlin with companion but no luck. It said

error: cannot find symbol
import my.package.name.HistoryItemBindingImpl;
                      ^
  symbol:   class HistoryItemBindingImpl
  location: package my.package.name

This is what i tried in kotlin

class Utils {
    companion object {
        fun formatUnixTime(timeInSeconds : Long, pattern: String) : String {
            val simpleDateFormat = SimpleDateFormat(pattern, Locale.US)
            val value = simpleDateFormat.format(Date(timeInSeconds * 1000))

            return value
        }
    }

And in xml

android:text='@{Utils.Companion.formatUnixTime(model.start_time, "hh:mm:ss")}'

Really hope someone can help. Thanks!

Update With @Max Aves help. I fixed my code and below code will work. Maybe it will help someone.

class Utils {
    companion object {
        @JvmStatic
        fun formatUnixTime(timeInSeconds : Long, pattern: String) : String {
            val simpleDateFormat = SimpleDateFormat(pattern, Locale.US)
            val value = simpleDateFormat.format(Date(timeInSeconds * 1000))

            return value
        }

And you can use this in xml

android:text='@{Utils.formatUnixTime(model.start_time, "hh:mm:ss")}'

回答1:

Have you tried adding @JvmStatic annotation? It may help Also, another possible solution is to use object instead of class

Any of these work for u?



回答2:

Utilities are generally created as Kotlin File. Because Kotlin files methods are global. Which you can use from anywhere without making it @JvmStatic.

BindingAdapterDefault.kt

fun formatUnixTime(timeInSeconds: Long, pattern: String): String {
    val simpleDateFormat = SimpleDateFormat(pattern, Locale.US)
    return simpleDateFormat.format(Date(timeInSeconds * 1000))
}

That will work for you same, NO class, brackets, companion, object etc...

From XML

<import type="com.innovanathinklabs.sample.ui2.BindingAdapterDefaultKt"/>

android:text="@{BindingAdapterDefaultKt.formatUnixTime(1540966388,`hh:mm:ss`)}"

That's all you need.

I want add more info about this. You can directly call this method from Java and Kotlin too.

From Java class

import static com.package.BindingAdapterDefaultKt.formatUnixTime;
formatUnixTime(454545, "hh:mm:ss");

From Kotlin class

import com.package.formatUnixTime
formatUnixTime(454545, "hh:mm:ss");

Suggestion

I prefer creating BindingAdapter which was introduced with Data Binding, and is very powerful thing. It gives me more flexibility across the app.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:formatSeconds="@{1540966388}"
    app:pattern="@{`hh:mm:ss`}"
    />

BindingAdapterDefault.kt

@BindingAdapter(value = ["formatSeconds", "pattern"])
fun secondsToDateText(textView: TextView, timeInSeconds: Long, pattern: String) {
    val simpleDateFormat = SimpleDateFormat(pattern, Locale.US)
    textView.text = simpleDateFormat.format(Date(timeInSeconds * 1000))
}