#android #android-livedata
#Android #android-livedata
Вопрос:
Я получаю aMVoice
от DetailViewModel
и представляю это в пользовательском интерфейсе для редактирования.
Я вызываю isChanged()
in FragmentDetail
и проверяю, изменилось ли содержимое aMVoice.
Я не могу получить правильный результат, я обнаружил, что он val b=(mDBVoiceRepository.getVoiceById(voiceId)).value
всегда возвращается null
, почему? Как я могу это исправить?
Код
class FragmentDetail : Fragment() {
private val mDetailViewModel by lazy {
getViewModel {
DetailViewModel( provideRepository(mContext), args.voiceId)
}
}
fun isChanged():Boolean{
mDetailViewModel.checkChanged()
return mDetailViewModel.isChanged.value!!
}
}
class DetailViewModel(private val mDBVoiceRepository: DBVoiceRepository, private val voiceId:Int) : ViewModel() {
val aMVoice=mDBVoiceRepository.getVoiceById(voiceId)
private val _isChanged= MutableLiveData<Boolean>(false)
val isChanged: LiveData<Boolean> = _isChanged
fun checkChanged(){
val a=aMVoice.value
val b=(mDBVoiceRepository.getVoiceById(voiceId)).value //It's null
_isChanged.value=!(a==b)
}
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
fun getVoiceById(id:Int)=mDBVoiceDao.getVoiceById(id)
}
interface DBVoiceDao{
@Query("SELECT * FROM voice_table where id=:id")
fun getVoiceById(id:Int):LiveData<MVoice>
}
@Entity(tableName = "voice_table", indices = [Index("createdDate")])
data class MVoice(
@PrimaryKey (autoGenerate = true) @ColumnInfo(name = "id") var id: Int = 0,
var name: String = "",
var path: String = ""
)
Комментарии:
1.
val a=aMVoice.value
Возвращает правильное значение?2. Спасибо!
val a=aMVoice.value
возвращает правильное значение
Ответ №1:
Мне кажется, что вы используете текущие данные, не наблюдая за ними, текущие данные не передают ant-данные, за исключением того, что у них есть активный наблюдатель. Итак, вы должны создать observer в своем фрагменте вместо ручной проверки значения.
Кроме того, нет необходимости сохранять переменные, чтобы определить, изменилось ли значение, live data может сделать это за вас с помощью distinctUntilChanged()
operator.
Итак, ваш код должен выглядеть примерно так, как показано ниже
class FragmentDetail : Fragment() {
private val mDetailViewModel by lazy {
getViewModel {
DetailViewModel(provideRepository(mContext), args.voiceId)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
observeVoiceChange()
}
fun observeVoiceChange() {
mDetailViewModel.checkChanged().distinctUntilChanged().observe(viewLifecycleOwner, Observer<MVoice> {
//Do whatever you want when voice changes
})
}
}
class DetailViewModel(private val mDBVoiceRepository: DBVoiceRepository, private val voiceId: Int) : ViewModel() {
fun checkChanged(): LiveData<MVoice> {
return (mDBVoiceRepository.getVoiceById(voiceId))
}
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao) {
fun getVoiceById(id: Int) = mDBVoiceDao.getVoiceById(id)
}
interface DBVoiceDao {
@Query("SELECT * FROM voice_table where id=:id")
fun getVoiceById(id: Int): LiveData<MVoice>
}
@Entity(tableName = "voice_table", indices = [Index("createdDate")])
data class MVoice(
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") var id: Int = 0,
var name: String = "",
var path: String = ""
)
как только фрагмент запускается, он должен отслеживать изменения в голосовых данных, возвращаться и работать с этими изменениями.