如何在Android启动submitList后立即刷新ListAdapter的数据源?
How can I refresh the data source of ListAdapter at once after I launch submitList in Android?
我使用 ListAdapter 作为 RecyclerView 的来源,它会显示 MVoice
的列表。数据源是mHomeViewModel.listVoiceBySort
,是LiveData<List<MVoice>>
,可以看代码A.
添加记录后,mHomeViewModel.listVoiceBySort.observe
会启动,myAdapter.submitList(it)
也会启动
但是我发现,最新的mHomeViewModel.listVoiceBySort
没有应用到ListAdapter,你可以看到Log A。
如何在启动submitList后立即刷新ListAdapter的数据源?
日志 A
E/My: itemCount: 13 it: 14 CurrentList:13
代码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
}
}
添加内容
致 Tenfour04:谢谢!
下面代码B是获取LiveDate的方法mHomeViewModel.listVoiceBySort
.
代码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() {
...
}
您应该像这样更改您的提交代码
mHomeViewModel.listVoiceBySort.observe(this.viewLifecycleOwner) {
(binding.recyclerViewVoice.adapter as YourAdapter).submitList(it.map { it.copy() })
Log.e("My","itemCount: "+myAdapter.itemCount+ " it: "+it.size+ " CurrentList:"+myAdapter.currentList.size)
}
您将列表引用提交给适配器,当某些内容发生变化时,它已经在适配器内部进行了更改,diffutil 找不到任何差异。您可以在提交时通过复制列表项来解决该问题。
submitList()
是异步的。在 submitList()
之后立即调用 myAdapter
上的其他方法可能无法反映您刚刚提交的列表。
相反,您可以 override onCurrentListChanged()
并在此时查看适配器。
或者,只计算您在屏幕上看到的行数。
我使用 ListAdapter 作为 RecyclerView 的来源,它会显示 MVoice
的列表。数据源是mHomeViewModel.listVoiceBySort
,是LiveData<List<MVoice>>
,可以看代码A.
添加记录后,mHomeViewModel.listVoiceBySort.observe
会启动,myAdapter.submitList(it)
也会启动
但是我发现,最新的mHomeViewModel.listVoiceBySort
没有应用到ListAdapter,你可以看到Log A。
如何在启动submitList后立即刷新ListAdapter的数据源?
日志 A
E/My: itemCount: 13 it: 14 CurrentList:13
代码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
}
}
添加内容
致 Tenfour04:谢谢!
下面代码B是获取LiveDate的方法mHomeViewModel.listVoiceBySort
.
代码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() {
...
}
您应该像这样更改您的提交代码
mHomeViewModel.listVoiceBySort.observe(this.viewLifecycleOwner) {
(binding.recyclerViewVoice.adapter as YourAdapter).submitList(it.map { it.copy() })
Log.e("My","itemCount: "+myAdapter.itemCount+ " it: "+it.size+ " CurrentList:"+myAdapter.currentList.size)
}
您将列表引用提交给适配器,当某些内容发生变化时,它已经在适配器内部进行了更改,diffutil 找不到任何差异。您可以在提交时通过复制列表项来解决该问题。
submitList()
是异步的。在 submitList()
之后立即调用 myAdapter
上的其他方法可能无法反映您刚刚提交的列表。
相反,您可以 override onCurrentListChanged()
并在此时查看适配器。
或者,只计算您在屏幕上看到的行数。