问题
I'm trying to delete an row of recyclerview using room.im doing swipe to delete a particular row....
here is my Address table-->
@Entity(tableName = "address")
class Address {
@PrimaryKey(autoGenerate = true)
var id = 0
@ColumnInfo(name = "address")
var address: String? = null
}
AddressDao:
@Dao
interface AddressDao {
@Insert
suspend fun addData(address: Address)
@Query("select * from address")
fun getAddressesWithChanges() :LiveData<MutableList<Address>>
@Query("SELECT EXISTS (SELECT 1 FROM address WHERE id=:id)")
suspend fun isAddressAdded(id: Int): Int
@Delete
suspend fun delete(address: Address)
}
Database:
@Database(entities = [Address::class], version = 1)
abstract class Database : RoomDatabase() {
abstract fun AddressDao(): AddressDao
}
AddressActivity:
class AddressActivity : AppCompatActivity() {
private val adapter = AddressAdapter()
private lateinit var data: LiveData<MutableList<Address>>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.address)
addbutton.findViewById<View>(R.id.addbutton).setOnClickListener {
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = adapter
recyclerView.addItemDecoration(DividerItemDecorator(resources.getDrawable(R.drawable.divider)))
recyclerView.addOnScrollListener(object :
RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
Log.e("RecyclerView", "onScrollStateChanged")
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
})
val application = application as CustomApplication
data = application.database.AddressDao(). getAddressesWithChanges()
data.observe(this, Observer { words1 ->
// Update the cached copy of the words in the adapter.
words1?.let { adapter.updateData(it) }})
}
}
Adapter:
class AddressAdapter: RecyclerSwipeAdapter<AddressAdapter.ViewHolder>() {
private var addresses: MutableList<Address> = Collections.emptyList()
lateinit var Database:Database
override fun onCreateViewHolder(viewGroup: ViewGroup, itemViewType: Int): ViewHolder =
ViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.address_item, viewGroup, false))
override fun getSwipeLayoutResourceId(position: Int): Int {
return R.id.swipe;
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
val fl: Address = addresses[position]
viewHolder.tv.setText(fl.address)
viewHolder.swipelayout.setShowMode(SwipeLayout.ShowMode.PullOut)
// Drag From Right
// Drag From Right
viewHolder.swipelayout.addDrag(
SwipeLayout.DragEdge.Right,
viewHolder.swipelayout.findViewById(R.id.bottom_wrapper)
)
// Handling different events when swiping
viewHolder.swipelayout.addSwipeListener(object : SwipeLayout.SwipeListener {
override fun onClose(layout: SwipeLayout) {
//when the SurfaceView totally cover the BottomView.
}
override fun onUpdate(layout: SwipeLayout, leftOffset: Int, topOffset: Int) {
//you are swiping.
}
override fun onStartOpen(layout: SwipeLayout) {}
override fun onOpen(layout: SwipeLayout) {
}
override fun onStartClose(layout: SwipeLayout) {}
override fun onHandRelease(
layout: SwipeLayout,
xvel: Float,
yvel: Float
) {
}
})
viewHolder.tvDelete.setOnClickListener(View.OnClickListener { view ->
mItemManger.removeShownLayouts(viewHolder.swipelayout)
addresses.removeAt(position)
//What should i do here??????????????????????????
// val address = Address()
// Database.AddressDao().delete(address)
notifyDataSetChanged()
notifyItemRemoved(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, addresses.size)
mItemManger.closeAllItems()
Toast.makeText(
view.context,
"Deleted " + viewHolder.tv.getText().toString(),
Toast.LENGTH_SHORT
).show()
})
// mItemManger is member in RecyclerSwipeAdapter Class
// mItemManger is member in RecyclerSwipeAdapter Class
mItemManger.bindView(viewHolder.itemView, position)
}
override fun getItemCount(): Int = addresses.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var tv: TextView
val swipelayout: SwipeLayout
val tvDelete:TextView
init {
tvDelete=itemView.findViewById(R.id.tvDelete)
tv = itemView.findViewById(R.id.ftv_name)
swipelayout=itemView.findViewById(R.id.swipe)
} }
fun updateData(addresses:
MutableList<Address>) {
this.addresses = addresses
notifyDataSetChanged() // TODO: use ListAdapter if animations are needed
}
}
From the above code im able delete a row at a moment but when i revisit the activity it shows that deleted row again
i want to know how can i delete a data which is stored in room using in onBindviewHolder
updated code of adapter as @Eishon: suggested
class AddressAdapter(context: Context): RecyclerSwipeAdapter<AddressAdapter.ViewHolder>() {
private var addresses: MutableList<Address> = Collections.emptyList()
val context: Context
var index = -1
var listener1: ListItemClick? = null
private var lastSelectedPosition = -1
init {
this.context = context
}
override fun onCreateViewHolder(viewGroup: ViewGroup, itemViewType: Int): ViewHolder =
ViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.address_item, viewGroup, false))
override fun getSwipeLayoutResourceId(position: Int): Int {
return R.id.swipe;
}
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.radio.setChecked(lastSelectedPosition == position);
val fl: Address = addresses[position]
viewHolder.tv.setText(fl.address)
// context.startActivity(i)
viewHolder.radio.setOnClickListener(View.OnClickListener {
lastSelectedPosition = position
notifyDataSetChanged()
index = position
notifyDataSetChanged()
val intent = Intent("custom-message1")
intent.putExtra("item1", fl.address)
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)
Toast.makeText(
context,
"selected offer is " ,
Toast.LENGTH_LONG
).show()
})
if (index === position) {
viewHolder.linearLayout.setBackgroundColor(Color.parseColor("#FF4081"))
} else {
viewHolder.linearLayout.setBackgroundColor(Color.parseColor("#FFFFFF"))
}
viewHolder.swipelayout.setShowMode(SwipeLayout.ShowMode.PullOut)
viewHolder.swipelayout.addDrag(
SwipeLayout.DragEdge.Right,
viewHolder.swipelayout.findViewById(R.id.bottom_wrapper)
)
viewHolder.swipelayout.addSwipeListener(object : SwipeLayout.SwipeListener {
override fun onClose(layout: SwipeLayout) {
}
override fun onUpdate(layout: SwipeLayout, leftOffset: Int, topOffset: Int) {
}
override fun onStartOpen(layout: SwipeLayout) {}
override fun onOpen(layout: SwipeLayout) {
}
override fun onStartClose(layout: SwipeLayout) {}
override fun onHandRelease(
layout: SwipeLayout,
xvel: Float,
yvel: Float
) {
}
})
viewHolder.tvDelete.setOnClickListener(View.OnClickListener { view ->
mItemManger.removeShownLayouts(viewHolder.swipelayout)
addresses.removeAt(position)
listener1?.onClick(position)
notifyDataSetChanged()
notifyItemRemoved(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, addresses.size)
mItemManger.closeAllItems()
Toast.makeText(
view.context,
"Deleted " + viewHolder.tv.getText().toString(),
Toast.LENGTH_SHORT
).show()
})
mItemManger.bindView(viewHolder.itemView, position)
}
override fun getItemCount(): Int = addresses.size
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var tv: TextView
val swipelayout: SwipeLayout
val tvDelete:TextView
var linearLayout: LinearLayout
var radio: RadioButton
init {
tvDelete=itemView.findViewById(R.id.tvDelete)
linearLayout =
itemView.findViewById(R.id.linearlayoutaddressitem)
/**/radio = itemView.findViewById(R.id.radiobutton)
tv = itemView.findViewById(R.id.ftv_name)
swipelayout=itemView.findViewById(R.id.swipe)
} }
fun updateData(addresses:
MutableList<Address>) {
this.addresses = addresses
notifyDataSetChanged() // TODO: use ListAdapter if animations are needed
}
fun updateData1(addresses: MutableList<Address>, listener1:ListItemClick)
{//how should i call this is activity??
this.addresses = addresses
this.listener1 = listener1
notifyDataSetChanged()
}
}
AddressActivity:
class AddressActivity : AppCompatActivity(),ListItemClick {
private lateinit var data: LiveData<MutableList<Address>>
private var data1:Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.address)
addbutton.findViewById<View>(R.id.addbutton).setOnClickListener {
val intent = Intent(this, AddAddressActivity::class.java)
startActivity(intent)
}
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
IntentFilter("custom-message1")
)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
val adapter = AddressAdapter(applicationContext)
recyclerView.adapter = adapter
recyclerView.addItemDecoration(DividerItemDecorator(resources.getDrawable(R.drawable.divider)))
recyclerView.addOnScrollListener(object :
RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
Log.e("RecyclerView", "onScrollStateChanged")
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
})
val application = application as CustomApplication
data = application.database.AddressDao(). getAddressesWithChanges()
data.observe(this, Observer { words1 ->
// Update the cached copy of the words in the adapter.
words1?.let { adapter.updateData(it) }})
}
}
}
override fun onClick(id: Int) {
val application = application as CustomApplication
data1 = application.database.AddressDao().deleteAddress(id)
}
}
回答1:
Could you try this:
viewHolder.tvDelete.setOnClickListener(View.OnClickListener { view ->
// this code is to have access to the database inside adapter you should find another way to do it,
// like pass database in contructor for ex...
val application = application as CustomApplication
Database = application.database.AddressDao()
// main code to delete in db
GlobalScope.launch(Dispatchers.IO) {
Database.delete(addresses[position])
}
//
mItemManger.removeShownLayouts(viewHolder.swipelayout)
addresses.removeAt(position)
....
回答2:
In Address DAO
@Query("DELETE FROM address WHERE id=:id")
fun deleteAddress(id: Int):Int
then call it from the position where your swipe operation is done.
Update:
Create an Interface like
interface ListItemClick{
fun onClick(int id)
}
implement on your Address activity class and pass this interface to the Adapter.
fun updateData(addresses:MutableList<Address>, listener:ListItemClick) {
this.addresses = addresses
this.listener = listener
notifyDataSetChanged()
}
then, where you implemented swipe to delete, call
listener.onClick(item_id)
on AddressActivity inside onClick of ListItemClick interface
val application = application as CustomApplication
data = application.database.AddressDao().deleteAddress(id)
I wrote it here, so some spelling mistake may remain. But,I think you got the basic idea.
来源:https://stackoverflow.com/questions/63266686/how-do-i-remove-row-from-recyclerview-using-room