3

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).

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

4 Comments

I want to link the 'click' with the BleutoothDevice as an argument back to the activity (so not to the adapter). How would you achieve this?
You can define your activity as a handler
That is a solution, but I'd rather not have my Activity in the BindingLayout, since it would make it unsuitable for reuse (since I can only use that layout with that Activity).
These days it is common to use a ViewModel, so the above would be `android:onClick="@{viewModel.onSomeClick}". That ViewModel should be for your Framgment or Activity (or even a specific View or feature), the Fragment/Activity can observe a LiveData from the ViewModel and route value updates to wherever they need to go (in your case to some main Activity it seems).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.