RecyclerView list from SQLite - Need help to implement "onclick"

I’ve created a list using the androidx.recyclerview.widget.RecyclerView. It gets its items from a SQLite database table.

When a item is clicked I belive this code is runned: clickLambda(currentItem.id)
My question is how can I get the ID or name of the item clicked?

Example I want when a item is clicked to have a function runned:

fun listOnClick(itemID: Int){
// TODO: How can I get the program to go here?
}

My code is located at GitHub.com/europa9/KotlinAndroidXRecycleViewSimpleSQLite. I’ll post it here as well:

MainActivity
package net.frindex.kotlinandroidxrecycleviewsimplesqlite

/**
 *
 * File: MainActivity.kt
 * Version 1.0
 * Date 24.10.2020
 * Copyright (c) 2020 S Ditlefsen
 * License: http://opensource.org/licenses/gpl-license.php GNU Public License
 *
 */

import android.database.Cursor
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.facebook.stetho.Stetho
import kotlinx.android.synthetic.main.activity_main.*
import net.frindex.kotlinandroidxrecycleviewsimplesqlite.db.DatabaseHelper
import net.frindex.kotlinandroidxrecycleviewsimplesqlite.recyclerViewAdapters.IdTitleAdapter
import net.frindex.kotlinandroidxrecycleviewsimplesqlite.recyclerViewAdapters.IdTitleDataClass
import java.util.ArrayList

class MainActivity : AppCompatActivity() {

    // Class variables
    var db: DatabaseHelper? = null
    private lateinit var categoriesList: ArrayList<IdTitleDataClass>


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // DB :: Open Chrome and go to URL chrome://inspect/#devices
        Stetho.initializeWithDefaults(this)

        // List categories
        listCategories()


    } // onCreate

    /*- List categories -------------------------------------------------------------------------- */
    fun listCategories(){

        // DB
        db = DatabaseHelper(this)

        // Fetch categories
        var categoriesCursor: Cursor? = db!!.rawQuery("SELECT category_id, category_name FROM categories")
        var categoriesSize: Int = categoriesCursor!!.count
        Log.d("listCategories()", "categoriesSize=" + categoriesSize)

        // Add a list of categories
        categoriesList = ArrayList<IdTitleDataClass>()
        while (categoriesCursor.moveToNext()) {
            val categoryId = categoriesCursor.getInt(0)
            val categoryName = categoriesCursor.getString(1)
            Log.d("listCategories()", "categoryId=" + categoryId + " categoryName=" + categoryName)
            categoriesList.add(IdTitleDataClass(categoryId, categoryName))

        }

        // Add to list
        recycler_view.adapter = IdTitleAdapter(categoriesList) {
            categoriesList[it]
        }
        recycler_view.layoutManager = LinearLayoutManager(this)
        recycler_view.setHasFixedSize(true)

    } // listCategories


    /*- List on click ---------------------------------------------------------------------------- */
    fun listOnClick(itemID: Int){
        // TODO: How can I get the program to go here?
    } // listOnClick
} // MainActivity

DatabaseHelper

package net.frindex.kotlinandroidxrecycleviewsimplesqlite.db

import android.content.Context
import android.database.Cursor
import android.database.DatabaseUtils
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper


class DatabaseHelper(context: Context):
    SQLiteOpenHelper(context, DB_NAME, null, DB_VERSIOM) {


    companion object {
        private val DB_NAME = "kotlinandroidxrecycleviewsimplesqlite"
        private val DB_VERSIOM = 1;
    }


    override fun onCreate(db: SQLiteDatabase?) {

        val q1 = "CREATE TABLE categories" +
                "(category_id Integer PRIMARY KEY, " +
                "category_name TEXT)"
        db?.execSQL(q1)

        val q2 = "INSERT INTO categories(category_id, category_name) " +
                "VALUES " +
                "(NULL, 'Bread and cereal')," +
                "(NULL, 'Bread')," +
                "(NULL, 'Cereals')," +
                "(NULL, 'Frozen bread and rolls')," +
                "(NULL, 'Crispbread')," +
                "(NULL, 'Sausage bread and lumps')," +
                "(NULL, 'Dessert and baking')," +
                "(NULL, 'Baking')," +
                "(NULL, 'Biscuit')," +
                "(NULL, 'Cakes')," +
                "(NULL, 'Buns')"
        db?.execSQL(q2)
    }

    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        db!!.execSQL("DROP TABLE IF EXISTS categories")

        onCreate(db)

    }

    // Query database - insert or update
    fun query(query: String): Boolean {
        val db = this.writableDatabase
        db.execSQL(query)
        db.close()
        return true;
    } // query

    // Count
    fun count(query: String): Int {
        val db = this.writableDatabase
        val numRows =
            DatabaseUtils.longForQuery(db, query, null).toInt()
        db.close()
        return numRows;
    }

    // Get
    fun rawQuery(query: String?): Cursor? {
        val db = this.writableDatabase
        val mCursor: Cursor = db.rawQuery(query, null)
        mCursor?.moveToFirst()
        return mCursor
    }


}

IdTitleAdapter

package net.frindex.kotlinandroidxrecycleviewsimplesqlite.recyclerViewAdapters

import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import net.frindex.kotlinandroidxrecycleviewsimplesqlite.R
import kotlinx.android.synthetic.main.adapter_id_title_item_layout.view.*

class IdTitleAdapter(val list: ArrayList<IdTitleDataClass>,val clickLambda: (Int)->Unit) : RecyclerView.Adapter<IdTitleViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IdTitleViewHolder {
        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.adapter_id_title_item_layout,parent,false)
        return IdTitleViewHolder(itemView)
    }


    override fun getItemCount(): Int {
        return list.size
    }


    override fun onBindViewHolder(holder: IdTitleViewHolder, position: Int) {
        val currentItem = list[position]
        holder.textViewTitle.text = currentItem.title
        holder.itemView.setOnClickListener {
            clickLambda(currentItem.id)
        }
    }

} // IdTitleAdapter

class IdTitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){

    val textViewTitle: TextView = itemView.textViewTitle

} // IdTitleViewHolder

IdTitleDataClass

package net.frindex.kotlinandroidxrecycleviewsimplesqlite.recyclerViewAdapters


data class IdTitleDataClass (val id:Int, val title:String)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/constraintLayout">


    <!-- Categories -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:listitem="@layout/adapter_id_title_item_layout"
        app:layout_constraintTop_toTopOf="parent" />
    <!-- //Categories -->


</androidx.constraintlayout.widget.ConstraintLayout>

adapter_id_title_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_marginTop="15dp"
        android:layout_marginBottom="15dp">
        <TextView
            android:id="@+id/textViewTitle"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:text="Title"
            android:textAlignment="center"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:textStyle="bold" />
    </LinearLayout>
</androidx.cardview.widget.CardView>

It seems like you already have answered your own question:

As you can see inside your code above, you are reading the item in position and holding it in currentItem.
As you have already used it there, you can use currentItem.id to access its id.

Please let me know if that helps… :slight_smile:

This sample is very useful. But is has also a problem.
The koltin synthetics are deprecated and you cannot create an apk any longer. You have to use ViewBinding that means migration.
The tutorial for migration is not detailled enough and it is not said how an adapter class and holder have to look like now.

Does anybody have advice for this problem?