I use ListAdapter as the source of a RecyclerView, it will display a list of MVoice
. The data source is mHomeViewModel.listVoiceBySort
, it's LiveData<List<MVoice>>
, you can see Code A.
After I added a record, mHomeViewModel.listVoiceBySort.observe
will be launched, myAdapter.submitList(it)
will be launched too.
But I found, the latest mHomeViewModel.listVoiceBySort
isn't applied to ListAdapter, you can see Log A.
How can I refresh the data source of ListAdapter at once after I launch submitList ?
Log A
E/My: itemCount: 13 it: 14 CurrentList:13
Code A
binding.recyclerViewVoice.adapter = myAdapter
mHomeViewModel.listVoiceBySort.observe(this.viewLifecycleOwner) {
myAdapter.submitList(it)
Log.e("My","itemCount: "+myAdapter.itemCount+ " it: "+it.size+ " CurrentList:"+myAdapter.currentList.size)
}
class VoiceAdapters (private val aHomeViewModel: HomeViewModel, private val mPlay: PlayInterface):
ListAdapter<MVoice, VoiceAdapters.VoiceViewHolder>(MVoiceDiffCallback()) {
private lateinit var mContext: Context
private lateinit var mLifecycleOwner:LifecycleOwner
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VoiceViewHolder {
mContext = parent.context
mLifecycleOwner = mContext as LifecycleOwner
return VoiceViewHolder(
LayoutVoiceItemBinding.inflate(LayoutInflater.from(parent.context), parent, false).also {
it.lifecycleOwner = mLifecycleOwner
it.aHomeViewModel = aHomeViewModel
}
)
}
override fun onBindViewHolder(holder: VoiceViewHolder, position: Int) {
val inputMVoice = getItem(position)
holder.bind(inputMVoice)
}
inner class VoiceViewHolder (private val binding: LayoutVoiceItemBinding):
RecyclerView.ViewHolder(binding.root) {
fun bind(inputMVoice: MVoice) {
binding.amVoice = inputMVoice
binding.executePendingBindings()
}
}
}
class MVoiceDiffCallback : DiffUtil.ItemCallback<MVoice>() {
override fun areItemsTheSame(oldItem: MVoice, newItem: MVoice): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: MVoice, newItem: MVoice): Boolean {
return oldItem == newItem
}
}
Added Content
To Tenfour04: Thanks!
The following Code B is how to get the LiveDate mHomeViewModel.listVoiceBySort
.
Code B
class HomeViewModel(val mApplication: Application, private val mDBVoiceRepository: DBVoiceRepository) : AndroidViewModel(mApplication) {
private val _listVoiceBySort=_sortBy.switchMap {
mDBVoiceRepository.listVoiceBySort(it)
}
val listVoiceBySort: LiveData<List<MVoice>> =_listVoiceBySort
...
}
class DBVoiceRepository private constructor(private val mDBVoiceDao: DBVoiceDao){
private val _isHaveRecord= MutableLiveData<Boolean>(false)
val isHaveRecord:LiveData<Boolean> =_isHaveRecord
fun listVoiceBySort(aSortBy: ESortBy): LiveData<List<MVoice>> {
var query=when (aSortBy){
ESortBy.StartPriority ->
"SELECT * FROM voice_table ORDER BY starred desc, createdDate desc"
ESortBy.DateDesc ->
"SELECT * FROM voice_table ORDER BY createdDate desc"
ESortBy.DateAsc ->
"SELECT * FROM voice_table ORDER BY createdDate"
ESortBy.TitleDesc ->
"SELECT * FROM voice_table ORDER BY title desc"
ESortBy.TitleAsc ->
"SELECT * FROM voice_table ORDER BY title"
}
return mDBVoiceDao.runtimeQuery(SimpleSQLiteQuery(query)).map {
_isHaveRecord.value =!it.isNullOrEmpty()
it
}
}
...
}
@Dao
interface DBVoiceDao{
@RawQuery(observedEntities = [MVoice::class])
fun runtimeQuery(sortQuery: SupportSQLiteQuery): LiveData<List<MVoice>>
...
}
abstract class DBVoiceDatabase : RoomDatabase() {
...
}
submitList()
is asynchronous. Calling other methods on myAdapter
right away after submitList()
may not reflect the list that you just submitted.
Instead, you could override onCurrentListChanged()
and look at the adapter at that point.
Or, just count the rows that you see on the screen. 😉