如何使用房间从回收站视图中删除一行? [英] How do I remove a row from recyclerview using room?
问题描述
我正在尝试使用 room.im 删除一行 recyclerview.我正在滑动以删除特定行....
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
}
地址道:
@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(entities = [Address::class], version = 1)
abstract class Database : RoomDatabase() {
abstract fun AddressDao(): AddressDao
}
地址活动:
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) }})
}
}
适配器:
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
}
}
从上面的代码中,我可以立即删除一行,但是当我重新访问活动时,它再次显示已删除的行
我想知道如何使用 onBindviewHolder
根据@quealegriamasalegre 建议的最新答案
这是我的自定义应用程序:--
Here is my CustomApplication:--
class CustomApplication: Application() {
lateinit var database: Database
private set
lateinit var addressDao: AddressDao
private set
override fun onCreate() {
super.onCreate()
this.database = Room.databaseBuilder<Database>(
applicationContext,
Database::class.java, "database"
).build()
addressDao = database.AddressDao()
}
}
现在适配器:
viewHolder.tvDelete.setOnClickListener(View.OnClickListener { view ->
mItemManger.removeShownLayouts(viewHolder.swipelayout)
addresses.removeAt(position)
val application = CustomApplication()
application.database.AddressDao().deleteAddress(position)//here you delete from DB so its gone for good
//notifyDataSetChanged() dont do this as it will reexecute onbindviewholder and skip a nice animation provided by android
//notifyItemRemoved(position) execute only once
notifyDataSetChanged()
notifyItemRemoved(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, addresses.size)
mItemManger.closeAllItems()
Toast.makeText(
view.context,
"Deleted " + viewHolder.tv.getText().toString(),
Toast.LENGTH_SHORT
).show()
})
现在因 kotlin.UninitializedPropertyAccessException 崩溃:lateinit 属性数据库尚未初始化
真的需要帮助....
推荐答案
按照我的简单步骤来解决您的问题,
Follow my simple steps to solve your issue,
第 1 步:检查一次 CustomApplication
名称是否在 AndroidManifest.xml
中提及,
Step 1:
Check once CustomApplication
name mentioned or not in AndroidManifest.xml
,
<application
android:name=".CustomApplication"
否则你会遇到这个问题
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myapplication/com.example.myapplication.AddressActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to com.example.myapplication.CustomApplication
第 2 步:检查您的模块级别 build.gradle
文件
Step 2:
Check your module level build.gradle
file
应用此更改
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
检查依赖关系 -- 对于 Kotlin,使用 kapt 而不是 annotationProcessor
check dependencies -- For Kotlin use kapt instead of annotationProcessor
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
否则你会遇到这个问题
java.lang.RuntimeException: cannot find implementation for com.example.myapplication.Database. Database_Impl does not exist
第 3 步:检查你的AddressDao
接口,添加这个功能
Step 3:
check your AddressDao
interface, add this function
@Delete
suspend fun deleteAddress(address: Address)
第 4 步:
在AddressAdapter
类中,添加这个监听器,
in AddressAdapter
class, add this listener,
interface ItemListener {
fun onItemClicked(address: Address, position: Int)
}
添加监听器变量和setListener函数
add listener variable and setListener function
private lateinit var listener: ItemListener
interface ItemListener {
fun onItemClicked(address: Address, position: Int)
}
fun setListener(listener: ItemListener) {
this.listener = listener;
}
然后在 tvDelete.setOnClickListener 方法中更新您的代码
then update your code in tvDelete.setOnClickListener method
viewHolder.tvDelete.setOnClickListener(View.OnClickListener { view ->
mItemManger.removeShownLayouts(viewHolder.swipelayout)
addresses.removeAt(position)
listener.onItemClicked(fl, position)
notifyDataSetChanged()
// notifyItemRemoved(position)
// notifyItemRangeChanged(position, addresses.size)
mItemManger.closeAllItems()
Toast.makeText(
view.context,
"Deleted " + viewHolder.tv.getText().toString(),
Toast.LENGTH_SHORT
).show()
})
第 5 步:在 AddressActivity
类中,进行此更改
Step 5:
In AddressActivity
class, do this changes
在这里实现监听器,
class AddressActivity : AppCompatActivity(), AddressAdapter.ItemListener {
然后覆盖方法
override fun onItemClicked(address: Address, position: Int) {
}
然后为适配器设置监听器
then set listener for adapter
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recyclerView.adapter = adapter
adapter.setListener(this)
然后在覆盖方法中更新代码
then update code in override method
override fun onItemClicked(address: Address, position: Int) {
lifecycleScope.launch {
val application = application as CustomApplication
application.database.AddressDao().deleteAddress(address)
}
}
这里我使用了协程,否则你也可以使用 AsycTask
here I used coroutine otherwise you can use AsycTask also
对于协程,在你的模块 build.gradle
文件中添加这个依赖项
for coroutine add this dependencies in your module build.gradle
file
implementation "android.arch.lifecycle:extensions:1.1.1"
kapt "android.arch.lifecycle:compiler:1.1.1"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
如果你在UI类中直接调用deleteAddress方法,就会出现这个问题
if you directly called deleteAddress method in UI class, you get this issue
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
所以在后台线程中使用这样的方法,
so use such methods in background thread,
如果您真的想在主 UI 线程中执行,请在代码中进行此更改
If you really want to execute in main UI thread, do this changes in your code
在AddressDao
接口中,
@Delete
fun deleteAddress(address: Address)
在CustomApplication
类中,添加allowMainThreadQueries()
class CustomApplication : Application() {
lateinit var database: Database
private set
lateinit var addressDao: AddressDao
private set
override fun onCreate() {
super.onCreate()
this.database = Room.databaseBuilder<Database>(
applicationContext,
Database::class.java, "database"
).allowMainThreadQueries().build()
addressDao = database.AddressDao()
}
}
这篇关于如何使用房间从回收站视图中删除一行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!