recyclerview一致性错误,第一次刷新工作正常,而第二次刷新得到错误。堆栈中没有行号。
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/parent_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="@color/white_color">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvPost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="19dp"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:spanCount="3" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
SwipeRefreshLayout swipeRefreshLayout = getView().findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
viewModel.refresh();
}
});
适配器代码
class DiscoverAdapter(private val action: (b: Int?) -> Unit)
: PagedListAdapter<PostModel, RecyclerView.ViewHolder>(NewsDiffCallback) {
private val DATA_VIEW_TYPE = 1
private val FOOTER_VIEW_TYPE = 2
private var state = State.LOADING
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return if (viewType == DATA_VIEW_TYPE) DiscoverViewHolder.create(parent) else ListFooterViewHolder.create(parent)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (getItemViewType(position) == DATA_VIEW_TYPE)
(holder as DiscoverViewHolder).bind(action, getItem(position))
else (holder as ListFooterViewHolder).bind(action, state)
}
override fun getItemViewType(position: Int): Int {
return if (position < super.getItemCount()) DATA_VIEW_TYPE else FOOTER_VIEW_TYPE
}
companion object {
val NewsDiffCallback = object : DiffUtil.ItemCallback<PostModel>() {
override fun areItemsTheSame(oldItem: PostModel, newItem: PostModel): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: PostModel, newItem: PostModel): Boolean {
return oldItem == newItem
}
}
}
override fun getItemCount(): Int {
return super.getItemCount() + if (hasFooter()) 1 else 0
}
private fun hasFooter(): Boolean {
return super.getItemCount() != 0 && (state == State.LOADING || state == State.ERROR)
}
fun setState(state: State) {
this.state = state
notifyItemChanged(super.getItemCount())
}
fun getData(position: Int): PostModel {
return getItem(position) as PostModel
}
}
View Holder 1是项目,另一项用于加载更多数据
class DiscoverViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(retry: (x: Int?) -> Unit, postModel: PostModel?) {
val width = DeviceScreenUtil.getInstance().width
val newWidth = width / 3
val layoutParams = itemView.rl_main_layout.getLayoutParams()
layoutParams.height = Math.round(newWidth * 1.2f)
layoutParams.width = Math.round(newWidth.toFloat())
itemView.rl_main_layout.setPadding(3, 3, 4, 4)
itemView.rl_main_layout.setLayoutParams(layoutParams)
if (postModel != null) {
// itemView.tv_total_like.text = news.title
if (!postModel.thumbnail.isNullOrEmpty())
Picasso.get().load(postModel.thumbnail).into(itemView.iv_image)
itemView.setOnClickListener { retry(adapterPosition) }
if (postModel.likes > 0) itemView.tv_total_like.setText(postModel.likes.toString() + "")
}
}
companion object {
fun create(parent: ViewGroup): DiscoverViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_myprofile, parent, false)
return DiscoverViewHolder(view)
}
}
}
设置适配器代码
DiscoverAdapter discoverAdapter = DiscoverAdapter {
if (it == null) {
viewModel.retry()
} else {
click(it)
}
}
rvPost.adapter = discoverAdapter
viewModel.newsList.observe(this,
Observer {
discoverAdapter.submitList(it)
})
刷新时无效数据源
错误日志
java.lang.IndexOutOfBoundsException:检测到不一致。无效的项目位置20(偏移量:20)。状态:21 androidx.recyclerview.widget.RecyclerView {ecd9c90 VFED ..... F .... ID 0,0-704,1024#7f08021d app:id / rvPost} ,适配器:com.app.ui.main.dashboard.search.discover.adapter.DiscoverAdapter@a9fb989,布局:androidx.recyclerview.widget.GridLayoutManager@97fed8e,上下文:com.app.ui.main.dashboard.MainActivity@226aa34 在androidx.recyclerview.widget.RecyclerView $ Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183) 在androidx.recyclerview.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:6118) 在androidx.recyclerview.widget.RecyclerView $ Recycler.getViewForPosition(RecyclerView.java:6114) 在androidx.recyclerview.widget.LinearLayoutManager $ LayoutState.next(LinearLayoutManager.java:2303) 在androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561) 在androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587) 在androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665) 在androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170) 在androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4085) 在androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3849) 在androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:625) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148) 在com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:43) 在com.google.android.material.appbar.AppBarLayout $ ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1892) 在androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:918) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148) 在com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:43) 在com.google.android.material.appbar.AppBarLayout $ ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1892) 在androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:918) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743) 在android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586) 在android.widget.LinearLayout.onLayout(LinearLayout.java:1495) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在android.widget.FrameLayout.layoutChildren(FrameLayout.java:336) 在android.widget.FrameLayout.onLayout(FrameLayout.java:273) 在android.view.View.layout(View.java:16651) 在android.view.ViewGroup.layout(ViewGroup.java:5440) 在安德罗伊
recyclerview适配器中存在问题,我认为您在刷新后再次设置数据时忘记了Adapte.rnotifyDataChanged():]
请打印您的适配器代码