#android #android-livedata
#Android #android-livedata
Вопрос:
У меня есть два LiveData
, aMVoice1
и aMVoice2
.
Я надеюсь проверить, равны ли они.
Я знаю, что мне нужно использовать observe
, чтобы получить значение LiveData.
поэтому я думаю, isEqual = (mDetailViewModel.aMVoice1.value==mDetailViewMode2.aMVoice1.value )
что это неправильно.
Но я думаю, что есть некоторые проблемы с fun observeVoice()
, как я могу это исправить?
class FragmentDetail : Fragment() {
private lateinit var binding: LayoutDetailBinding
private val mDetailViewModel by lazy {
...
}
var isEqual=false
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
binding.lifecycleOwner = this.viewLifecycleOwner
binding.aDetailViewModel=mDetailViewModel
isEqual = (mDetailViewModel.aMVoice1.value==mDetailViewMode2.aMVoice1.value ) // I don't think it's correct.
observeVoice()
return binding.root
}
fun observeVoice() {
mDetailViewModel.aMVoice1.observe(viewLifecycleOwner){value1->
isEqual = (value1==mDetailViewModel.aMVoice2.value) // mDetailViewModel.aMVoice2.value maybe null
}
}
}
class DetailViewModel(private val mDBVoiceRepository: DBVoiceRepository, private val voiceId1:Int,private val voiceId2:Int) : ViewModel() {
val aMVoice1=mDBVoiceRepository.getVoiceById(voiceId1)
val aMVoice2=mDBVoiceRepository.getVoiceById(voiceId2)
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
fun getVoiceById(id:Int)=mDBVoiceDao.getVoiceById(id)
}
@Dao
interface DBVoiceDao{
@Query("SELECT * FROM voice_table where id=:id")
fun getVoiceById(id:Int):LiveData<MVoice>
}
data class MVoice(
@PrimaryKey (autoGenerate = true) @ColumnInfo(name = "id") var id: Int = 0,
var name: String = "",
var path: String = ""
)
Добавленный контент
Это нормально для следующего кода?
fun observeVoice() {
mDetailViewModel.aMVoice1.observe(viewLifecycleOwner){value1->
mDetailViewModel.aMVoice2.observe(viewLifecycleOwner){value2->
isEqual = (value1==value2)
}
}
}
Комментарии:
1. Почему бы вам не попробовать наблюдать aMVoice2 в рамках observe aMVoice1
2. для этого вы можете использовать ‘MediatorLiveData’, смотрите Здесь , найдите
combineLatestData
3. Спасибо! Хеллиусу, не могли бы вы посмотреть мой добавленный контент в вопросе?
Ответ №1:
Согласно официальным документам, лучший способ достичь решения для таких случаев — использовать MediatorLiveData
как LiveData
слияние. Используя его, вы можете проверить равенство значений, когда новое значение публикуется в любом из LiveData
s:
class DetailViewModel(...) : ViewModel() {
val areMVoicesEqual = MediatorLiveData<Boolean>().apply {
addSource(aMVoice1) { postValue(it == aMVoice2.value) }
addSource(aMVoice2) { postValue(it == aMVoice1.value) }
}
}
Затем:
fun observeVoice() {
mDetailViewModel.areMVoicesEqual.observe(viewLifecycleOwner){ equality ->
// do whatever you want with `equality`
}
}
Обратите внимание, что упомянутый вами фрагмент добавленного содержимого неверен. Фактически, в этом случае каждый раз, когда значение наблюдается на aMVoice1
, новое Observer
начинает наблюдаться на aMVoice2
, что неверно.