所以,当我以Recyclerview的形式显示保存的数据后,我试图通过调用Dao接口中声明的delete方法,在recyclerview类中声明的imageView上单击listener后删除特定位置的数据。我遵循MVVM模式。但是当我单击imageView时,没有任何动作发生。
recyclerview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_margin="20dp"
android:background="@drawable/rounded_cardview"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:layout_gravity="center"
android:id="@+id/textView"
style="@style/word_title"
android:textColor="#FFFF"
android:paddingStart="20dp"
android:textStyle="bold"
android:layout_marginStart="30dp"
android:text="@string/word1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:layout_gravity="center"
android:text="@string/word2"
android:textColor="#FFFF"
android:textStyle="bold"
android:id="@+id/text1"
style="@style/word_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageDelete"
android:src="@drawable/baseline_delete_24"
android:layout_gravity="center"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp" />
</LinearLayout>
second.xml
<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=".SecondActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/rounded_button"
tools:listitem="@layout/recyclerview"
android:padding="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:contentDescription="@string/add_word"/>
</androidx.constraintlayout.widget.ConstraintLayout>
第二个活动.kt
class SecondActivity:AppCompatActivity() {
lateinit var binding: SecondBinding
val cardViewmodel: CardViewmodel by viewModels{
WordViewModelFactory((application as CardsApplication).repository)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = SecondBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = CardListAdapter()
binding.recyclerview1.adapter = adapter
binding.recyclerview1.layoutManager = LinearLayoutManager(this)
cardViewmodel.allWords.observe(this) { cardPairs ->
for (cardpair in cardPairs) {
adapter.submitList(cardPairs)
}
}
val inflator = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
val view = inflator.inflate(R.layout.recyclerview,null)
val imageDelete = view.findViewById<ImageView>(R.id.imageDelete)
imageDelete.setOnClickListener {
// Get the position of the clicked item
val position = binding.recyclerview1.getChildAdapterPosition(view)
// Get the CardPair object from the adapter using the position
val cardPair = adapter.currentList[position]
// Call the delete() method on your CardViewmodel to delete the CardPair from the database
cardViewmodel.deleteCards(cardPair)
// Notify the adapter that the data has changed
adapter.notifyItemRemoved(position)
}
}
}
Cardviewmodel.kt
class CardViewmodel(private val repository:CardPairRepository) : ViewModel() {
// Using LiveData and caching what allWords returns has several benefits:
// - We can put an observer on the data (instead of polling for changes) and only update the
// the UI when the data actually changes.
// - Repository is completely separated from the UI through the ViewModel.
val allWords: LiveData<List<CardPair>> = repository.allWords.asLiveData()
/**
* Launching a new coroutine to insert the data in a non-blocking way
*/
fun insertCards(pair: CardPair) = viewModelScope.launch {
repository.insert(pair)
}
fun deleteCards(pair: CardPair) = viewModelScope.launch {
repository.deleteCard(pair)
}
}
class WordViewModelFactory(private val repository:CardPairRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(CardViewmodel::class.java)) {
@Suppress("UNCHECKED_CAST")
return CardViewmodel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
CardListAdapter.kt
class CardListAdapter : ListAdapter<CardPair,CardListAdapter.WordViewHolder>(WordsComparator()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
return WordViewHolder.create(parent)
}
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val current = getItem(position)
val current1 = getItem(position)
holder.bind(current.front,current1.back)
}
class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val wordItemView: TextView = itemView.findViewById(R.id.textView)
private val deftext: TextView = itemView.findViewById(R.id.text1)
fun bind(text: String?,text1: String?) {
wordItemView.text = text
deftext.text=text1
}
companion object {
fun create(parent: ViewGroup): WordViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.recyclerview, parent, false)
return WordViewHolder(view)
}
}
}
class WordsComparator : DiffUtil.ItemCallback<CardPair>() {
override fun areItemsTheSame(oldItem:CardPair, newItem:CardPair): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem:CardPair, newItem:CardPair): Boolean {
return oldItem.front == newItem.front && oldItem.back==newItem.back
}
}
}
存储库类的构成如下
class CardPairRepository(private val cardPairDao: CardPairDao) {
// Room executes all queries on a separate thread.
// Observed Flow will notify the observer when the data has changed.
val allWords: Flow<List<CardPair>> = cardPairDao.getAlphabetizedWords()
// By default Room runs suspend queries off the main thread, therefore, we don't need to
// implement anything else to ensure we're not doing long running database work
// off the main thread.
@Suppress("RedundantSuspendModifier")
@WorkerThread
suspend fun insert(pair: CardPair) {
cardPairDao.insertWord(pair)
}
@WorkerThread
suspend fun deleteCard(pair: CardPair){
cardPairDao.deleteWord(pair)
}
}
用于设置房间数据库的数据类
@Entity(tableName = "word_table")
data class CardPair(
@PrimaryKey @ColumnInfo(name = "front") val front: String,
@ColumnInfo(name = "back") val back: String
)
接口CardPairDao.kt
@Dao
interface CardPairDao {
@Query("SELECT * FROM word_table ORDER BY front ASC, back ASC")
fun getAlphabetizedWords(): Flow<List<CardPair>>
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insertWord(pair: CardPair)
@Delete
suspend fun deleteWord(pair: CardPair)
}
房间数据库类显示在CardRoomDatabase.kt下面
@Database(entities = [CardPair::class], version = 2, exportSchema = true)
abstract class CardRoomDatabase : RoomDatabase() {
abstract fun cardPairDao(): CardPairDao
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
var wordDao = database.cardPairDao()
wordDao.getAlphabetizedWords()
}
}
}
}
companion object {
@Volatile
private var INSTANCE:CardRoomDatabase? = null
fun getDatabase(
context: Context,
scope: CoroutineScope
):CardRoomDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
CardRoomDatabase::class.java,
"word_database"
)
.addCallback(WordDatabaseCallback(scope))
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
// return instance
instance
}
}
}
}
1条答案
按热度按时间qhhrdooz1#
根据您提供的代码,看起来您正在布局中的ImageView上设置单击侦听器,而该布局不是RecyclerView布局的一部分。
要修复此问题,可以在RecyclerView适配器的onBindViewHolder方法中设置ImageView上的单击侦听器