简单问题:Android Kotlin LiveData observe 函数在我删除它试图观察的项目后导致空指针异常
Easy Problem: Android Kotlin LiveData observe function causes null pointer exception after I delete the item its trying to observe
我正在使用空间来管理我的本地字典数据库。我 select 一个词然后删除它,它应该导航回主页。然而,有时,在删除单词后,它会导致空指针异常,试图访问我已删除的单词。当异常确实发生时,我可以简单地尝试捕获异常,但我认为我缺少对这些生命周期如何工作的基本理解,如果可能的话,我希望有更好的方法来实现它。我很感激这里的任何帮助。
这是我片段中删除函数的代码:
private fun deleteItem() {
viewModel.deleteWord(word)
findNavController().navigateUp()
}
不确定是否需要,但这是我的 dao,没有使用存储库。
@Dao
interface DictionaryDao {
@Query("SELECT * FROM dictionary") // can alter this to order by word for example
fun getAll(): Flow<List<DictionaryData>>
@Query("SELECT * from dictionary WHERE id=:id")
fun getContents(id: Int): Flow<DictionaryData>
@Query("SELECT word FROM dictionary")
fun getWordsList(): Flow<List<String>>
@Insert (onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(word: DictionaryData)
@Update
suspend fun update(word: DictionaryData)
@Delete
suspend fun delete(word: DictionaryData)}
这里最重要的是观察者在我删除它后一直试图访问我的单词对象的片段。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val id = navigationArgs.itemId
viewModel.retrieveData(id).observe(viewLifecycleOwner) { selectedItem ->
word = selectedItem
bind(word)
}
}
而 selectedItem 对象是导致崩溃的原因:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app1.personalpocketdictionary, PID: 12648
java.lang.NullPointerException: selectedItem must not be null
at com.app1.personalpocketdictionary.fragments.ItemDetailFragment.onViewCreated$lambda-6(ItemDetailFragment.kt:114)
最后来自 viewModel 的是使用的两个相关函数:
fun deleteWord(word: DictionaryData){
viewModelScope.launch {
dictionaryDao.delete(word)
Log.d("devNotes", "doa delete successful")
}
}
和
fun retrieveData(id: Int) : LiveData<DictionaryData>{
return dictionaryDao.getContents(id).asLiveData()
}
我想在删除该项目甚至导航到另一个片段并完成我们导航到的新片段的 onViewCreated 函数后,这个观察函数将不再使用,但不,它仍然存在,试图获取该数据。但只是有时!当我删除时,一半时间它崩溃,一半时间它工作。 idk man 请发送帮助。
如果它有点令人困惑,请 lmk 我很乐意进一步澄清
您正在观察对数据库的查询结果,您可以在其中获取具有您用于启动片段的 ID 的项目的值。我猜你用那个“词”来显示数据。但是当从数据库中删除对象时,观察者仍然存在,然后查询具有该 ID returns null 的数据库,因为该对象不再存在。所以“word”是空的。并且“单词”未声明为可为空。
当您使用 navigateUp 时,片段不会立即删除,而是会转到后台堆栈并在那里发生崩溃。
我可以想到两种方法来解决这个问题:
1- 您将单词声明为可为空
var word: Object?
2-你比较观察者的结果值
...
selectedItem?.let{
word = it
bind(word)
}
...
我正在使用空间来管理我的本地字典数据库。我 select 一个词然后删除它,它应该导航回主页。然而,有时,在删除单词后,它会导致空指针异常,试图访问我已删除的单词。当异常确实发生时,我可以简单地尝试捕获异常,但我认为我缺少对这些生命周期如何工作的基本理解,如果可能的话,我希望有更好的方法来实现它。我很感激这里的任何帮助。
这是我片段中删除函数的代码:
private fun deleteItem() {
viewModel.deleteWord(word)
findNavController().navigateUp()
}
不确定是否需要,但这是我的 dao,没有使用存储库。
@Dao
interface DictionaryDao {
@Query("SELECT * FROM dictionary") // can alter this to order by word for example
fun getAll(): Flow<List<DictionaryData>>
@Query("SELECT * from dictionary WHERE id=:id")
fun getContents(id: Int): Flow<DictionaryData>
@Query("SELECT word FROM dictionary")
fun getWordsList(): Flow<List<String>>
@Insert (onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(word: DictionaryData)
@Update
suspend fun update(word: DictionaryData)
@Delete
suspend fun delete(word: DictionaryData)}
这里最重要的是观察者在我删除它后一直试图访问我的单词对象的片段。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val id = navigationArgs.itemId
viewModel.retrieveData(id).observe(viewLifecycleOwner) { selectedItem ->
word = selectedItem
bind(word)
}
}
而 selectedItem 对象是导致崩溃的原因:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app1.personalpocketdictionary, PID: 12648
java.lang.NullPointerException: selectedItem must not be null
at com.app1.personalpocketdictionary.fragments.ItemDetailFragment.onViewCreated$lambda-6(ItemDetailFragment.kt:114)
最后来自 viewModel 的是使用的两个相关函数:
fun deleteWord(word: DictionaryData){
viewModelScope.launch {
dictionaryDao.delete(word)
Log.d("devNotes", "doa delete successful")
}
}
和
fun retrieveData(id: Int) : LiveData<DictionaryData>{
return dictionaryDao.getContents(id).asLiveData()
}
我想在删除该项目甚至导航到另一个片段并完成我们导航到的新片段的 onViewCreated 函数后,这个观察函数将不再使用,但不,它仍然存在,试图获取该数据。但只是有时!当我删除时,一半时间它崩溃,一半时间它工作。 idk man 请发送帮助。
如果它有点令人困惑,请 lmk 我很乐意进一步澄清
您正在观察对数据库的查询结果,您可以在其中获取具有您用于启动片段的 ID 的项目的值。我猜你用那个“词”来显示数据。但是当从数据库中删除对象时,观察者仍然存在,然后查询具有该 ID returns null 的数据库,因为该对象不再存在。所以“word”是空的。并且“单词”未声明为可为空。 当您使用 navigateUp 时,片段不会立即删除,而是会转到后台堆栈并在那里发生崩溃。 我可以想到两种方法来解决这个问题:
1- 您将单词声明为可为空
var word: Object?
2-你比较观察者的结果值
...
selectedItem?.let{
word = it
bind(word)
}
...