Search code examples
androidlistviewkotlinbaseadapter

Is there any way to refresh custom view inside baseadapter after updating data?


I have a custom view inside a baseadapter that is shown on listview. Currently I can update the items inside database but I cannot refresh the view. I want to refresh the view automatically after updating.Is there anyway to refresh? Please take a look at my code.

This is modle class-

class Item_Detail {
   var qty:Int = 0
   var id:Int = 0
   constructor()}

This is DatabaseHandler-

  val Detail: List<Item_Detail>
    get() {
        val bb=this.writableDatabase
        val seItem=ArrayList<Item_Detail>()
        val myPath=DB_PATH + REAL_DATABASE
        val db=SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY)
        val selectQuery="Select * From Transaction_table Where date='$rowview_date' And location='$rowview_location'"
        val cursor=db.rawQuery(selectQuery, null)

        if (cursor.moveToFirst()) {

            do {
                val item=Item_Detail()
                item.id=cursor.getInt(cursor.getColumnIndex("_id2"))
                item.qty=cursor.getInt(cursor.getColumnIndex("quantity2"))
                seItem.add(item)
            } while(cursor.moveToNext())
        }
        db.close()
        return seItem
    }

This is MainActivity-

class Detail : AppCompatActivity() {

internal lateinit var db: DataBaseHelper
internal var seItem: List<Item_Detail> = ArrayList<Item_Detail>()

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

    db = DataBaseHelper(this)
    detail_date.text = rowview_date.toString()
    detail_location.text = rowview_location.toString()
    getDetail()


}
private fun getDetail() {
    seItem = db.Detail
    val adapter = Adapter_detail(this, seItem,this)
    list_detail.adapter=adapter
    list_detail.invalidate()
}}

This is Adapterclass-

  class Adapter_detail(
    internal var activity: Activity,
    internal var stitem: List<Item_Detail>,
    val context:Context

    ) : BaseAdapter() {

internal lateinit var db: DataBaseHelper
internal var inflater: LayoutInflater

init {
    inflater = activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
}

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

    val rowView:View
    rowView = inflater.inflate(R.layout.detail_row, null)
    rowView.detail_id.text = stitem[position].id.toString()
    rowView.detail_qty.text = stitem[position].qty.toString()


    rowView.btn_detail.setOnClickListener{
        db=DataBaseHelper(context)//Initiate the database
        val builder=android.app.AlertDialog.Builder(context)
        inflater=activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater

        val view=inflater.inflate(R.layout.edit_layout, null)
        builder.setView(view)
        val dialog: android.app.AlertDialog=builder.create()

        var tran_edit=view.findViewById<EditText>(R.id.edt_edit)
        tran_edit.setText(stitem[position].qty.toString())

        dialog.show()

        var btn_edt=view.findViewById<Button>(R.id.btn_edit)
        btn_edt.setOnClickListener {
            val item=Item(
                Integer.parseInt(stitem[position].id.toString()),
                Integer.parseInt(1.toString()),
                tran_edit.text.toString(),
                name.toString(),
                record_date.toString(),
                record_location.toString(),
                master_record.toString().toInt()
            )
            db.updateItem(item)
            dialog.dismiss()
        }
    }

    return rowView

}

override fun getItem(position: Int): Any {
    return stitem[position]
}

override fun getItemId(position: Int): Long {
    return stitem[position].id!!.toLong()
}

override fun getCount(): Int {
    return stitem.size
}

Solution

  • You need to call notifyDataSetChanged() on your adapter object when you refresh data. You need to do following changes to make use of it,

    MainActivity

    class Detail : AppCompatActivity() {
    
        internal lateinit var db: DataBaseHelper
        internal var seItem: MutableList<Item_Detail> = ArrayList<Item_Detail>()
        internal lateinit var adapter : Adapter_detail
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_detail)
    
            db = DataBaseHelper(this)
            detail_date.text = rowview_date.toString()
            detail_location.text = rowview_location.toString()
            adapter = Adapter_detail(this, seItem,this)
            list_detail.adapter=adapter
            getDetail()
        }
    
        private fun getDetail() {
            adapter.refresh(db.Detail)
        }
    
    }
    

    Adapterclass

    class Adapter_detail(
        internal var activity: Activity,
        internal var stitem: MutableList<Item_Detail>,
        val context:Context
    
        ) : BaseAdapter() {
    
        ...
    
        fun refresh(newList: List<Item_Detail>) {
             stitem.clear()
             stitem.addAll(newList)
             notifyDataSetChanged()
        }
    
    }
    

    N.B. I wrote this solution using mobile so please excuse any syntax error. Let me know if it works?

    P.S. There is a better adapter implementation i.e. CursorAdapter which is especially designed for using with database cursor. You can follow this tutorial to integrate it.

    Update

    I forgot one thing, you need to call refresh() inside your ClickListener callback in getView() function where you perform the update operation. So, it will look like as follows,

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        ...
    
            btn_edt.setOnClickListener {
                val item= ...
                db.updateItem(item)
                dialog.dismiss()
                refresh(db.Detail)
            }
        }
    
        return rowView
    }