Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace java generic interface in Kotlin for Databinding

I'm getting to know Kotlin as an Android developer. When making android apps, I'm used to using Databinding, retrolambda, etc. Now I'm a bit lost in how to solve the following case in Kotlin.

How I would normally do this in java

I have an Adapter (extends RecyclerView.Adapter) for a RecyclerView showing a list of BluetoothDevices. Normally, all my projects have a generic interface TypedClickListener, which will give back the T object of the listitem the user clicked on. Like so:

The generic interface:

public interface TypedClickListener<T> {
    void onClick(T t);
}

Constructor of PairedDeviceAdapter

public PairedDeviceAdapter(Context context, BluetoothDevice[] devices, TypedClickHandler<BluetoothDevice> handler){
    mContext = context;
    mDevices = devices
    mClickHandler = handler;
}

The adapter's onBindViewHolder: (the holder contains a databinding layout)

public void onBindViewHolder(DatabindViewHolder holder, Int position) {
    holder.getBinding().setVariable(BR.device, mDevices[position]);
    holder.getBinding().setVariable(BR.handler, mClickHandler);
}

The layout itself:

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="android.bluetooth.BluetoothDevice"/>
        <import type="com.example.TypedClickHandler"/>
        <variable
            name="device"
            type="BluetoothDevice"/>
        <variable
            name="handler"
            type="TypedClickHandler"/>
    </data>
    <LinearLayout
        ... // width, height, etc
        android:onClick="@{v->handler.onClick(device)}">
        ... // Row layout etc
    </LinearLayout>
</layout>

Now, putting everything together:

Passing the TypedClickListener to the Adapter in the Activity:

mAdapter = PairedDeviceAdapter(this, devices, (bluetoothDevice) -> {
    // The code that is ran when user clicks a device
}

How I'm trying to do this in Kotlin

As said, I'm trying to do this with Kotlin. It seems I can skip the step of having a TypedClickListener, since I can use a simple inline function (BluetoothDevice) -> Unit.

The PairedDeviceAdapter looks like this:

class PairedDeviceAdapter(val context: Context, val clickHandler : (BluetoothDevice) -> Unit ) : RecyclerView.Adapter<DatabindViewHolder>() {

The onBindViewHolder looks kinda the same as the Java version of it. However, I can't figure out how to bind my layout to the clickhandler, since I don't have the type of the clickhandler.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="android.bluetooth.BluetoothDevice"/>
        <import type="???"/>
        <variable
            name="device"
            type="BluetoothDevice"/>
        <variable
            name="handler"
            type="???"/>
    </data>
    <LinearLayout
        ...
        android:onClick="@{v->handler.???(device)}">
        ... // close everything

Question

How can I make this same structure in Kotlin, or is there another (smarter?) solution to binding a adapter-row-click to a lambda function defined in the Activity (or Fragment).

like image 500
Marcel50506 Avatar asked Apr 16 '26 10:04

Marcel50506


1 Answers

You can just have a method, for example onSomeClick() in your class, and call it like this: android:onClick="@{onSomeClick}"

like image 115
John Avatar answered Apr 18 '26 22:04

John