如何解决房间数据库中更新时的重复数据条目
在这个应用程序中,我试图在用户更改现有笔记时自动保存笔记。因此,我使用 textWatcher
并在文本观察器的 saveNotes()
方法中调用 onTextChanged()
方法。因此,我打算在每次用户从文本中添加或删除任何字符时保存注释。
var ide: Int? = null //Global Variable
//in OnCreate()
if(intent.getBooleanExtra("isViewOrUpdate",false)){
viewOrOpenednote = intent.getSerializableExtra("note") as Note?
ide = viewOrOpenednote?.id
在上面的两个代码示例中..整个想法是让变量 ide
充当检查器,即如果用户正在创建新笔记,它将返回 null 否则,它将存储笔记的 id 如果用户已打开现有笔记以查看或编辑该笔记。
下面是textWatcher
title_edit_text.addTextChangedListener((object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?,p1: Int,p2: Int,p3: Int) {}
override fun onTextChanged(p0: CharSequence?,p3: Int) {
saveNote() // here I
}
override fun afterTextChanged(p0: Editable?) {}
}))
saveNote()
private fun saveNote() {
val note = Note()
note.setTitle(Title)
if (ide != null) {
note.setId(ide!!) // Here I am assigning the note id to `ide` in case the
`saveNote()` is called when user has opened an existing note. If
this is a new note then ide will be null automatically.
}
class SaveNotes : AsyncTask<Void,Void,Void>() {
override fun doInBackground(vararg void: Void?): Void? {
NotesDatabase.getDatabase(applicationContext).noteDao().insertNote(note)
return null
}
override fun onPostExecute(result: Void?) {
super.onPostExecute(result)
ide = note.id //This is because: If user has added a first
character in new note,then after that an id will be
assigned to this new database,whenever
`saveNote()` method is called again after text change
I need to save the changed note to the same existing
id. I hope I am clear.
// ***UPDATE*** After much contemplation I have found out
that here lies the problem! changing the value of ide by
simply `ide = note.id` will always give null value for new
note,as this id is not received from the created note,but from the blank note instance I created above.
}
}
SaveNotes().execute()
}
问题:即使采取了上述预防措施,每次我更改笔记时,都会创建同一笔记的多个实例。示例:
假设我输入:你好
我得到的结果是 5 个不同 id 的不同笔记。和文字如下:
h //id = 5
他 //id = 4
hel //id = 3
地狱//id = 2
你好 //id = 1
NoteDao.java
@Dao
public interface NoteDao {
@Query("SELECT * FROM note ORDER BY id DESC")
List<Note> getAllNotes();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertNote(Note note);
@Delete
void delete(Note note);
}
Note.java
@Entity(tableName = "note")
public class Note implements Serializable {
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "title")
NoteDatabase.java
public static synchronized NotesDatabase getDatabase(Context context)
{
if(notesDatabase == null){
notesDatabase = Room.databaseBuilder(context,NotesDatabase.class,"note_db"
)
.addMigrations(MIGRATION_1_2)
.build();
}
return notesDatabase;
}
public abstract NoteDao noteDao();
解决方法
每次在 onTextChange 中调用 saveNote 时,您都会创建一个新实例 (viewOrOpenedNote),因此传递您从数据库中获取或当前显示给用户的旧实例便笺对象。
//Pass the same note instance which you are showing on the screen.
@Update
fun updateNote(note: Note)
//Give note the same id as It saved in the previous note. e-g create a note instance but set Id = viewOrOpenedNote.id so that is where Conflict will arise and the database will replace it.
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertNote(note: Note) : Long
使用协程
第一步:
def coroutines_android_version = '1.3.9'
// Coroutines libraries
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_core"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_android_version"
第二步:
在班级层面明确它。
private val ioScope = CoroutineScope(Dispatchers.IO)
第三步:
ioScope.launch {
saveNote()
}
suspend fun saveNote(){
NotesDatabase.getDatabase(applicationContext).noteDao().insertNote(note)
}
,
像这样在你的 Dao 中创建一个函数
@Update(onConflict = OnConflictStrategy.REPLACE)
fun update(note: Note): Int
并将以下代码放入您的 saveNote 函数中
fun saveNote(item: Note) {
database.runInTransaction {
val id = item.id
if(id == null)
getNoteDao().insert(item)
else
getNoteDao().update(item)
}
}
,
总结
考虑到您在 postExecuteMethod() 中指出 ide = note.id
处的错误所做的更改。执行以下操作:
1. 用这个
更改NoteDao.java中的插入块@Insert(onConflict = OnConflictStrategy.REPLACE)
long insertNote(Note note); //long istead of void if you need the id as return
2.
将 ide
的数据类型从 int
var ide: Long? = null
3.
在onCreate()
if(intent.getBooleanExtra("isViewOrUpdate",false)){
viewOrOpenedNote = intent.getSerializableExtra("note") as Note?
ide = viewOrOpenedNote?.id?.toLong() //Convert to long
4.
您现在只需要用下面的块替换 saveNote()
方法。
private fun saveNote() {
val database = NotesDatabase.getDatabase(applicationContext) //add this here
val note = Note()
note.setTitle(Title)
if (ide != null) {
note.setId(ide!!.toInt()) //convert to int as ide is long
}
class SaveNotes : AsyncTask<Void,Void,Void>() {
override fun doInBackground(vararg void: Void?): Void? {
ide = database.noteDao().insertNote(note) // two things inone line: first insert the note and then get the id of the note saved
return null
}
override fun onPostExecute(result: Void?) {
super.onPostExecute(result)
// Let this be empty
}
}
SaveNotes().execute()
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。