Solution 1 :
problem exist in recyclerview adapter i think you forget to adapte.rnotifyDataChanged() when set data again after refresh 🙂
plz print your adapter code
Problem :
recyclerview consistency error one first refresh working properly on second refresh getting error. no line number in stack.
<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();
}
});
Adapter Code
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 is items and another use for load more data
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)
}
}
}
set adapter code
DiscoverAdapter discoverAdapter = DiscoverAdapter {
if (it == null) {
viewModel.retry()
} else {
click(it)
}
}
rvPost.adapter = discoverAdapter
viewModel.newsList.observe(this,
Observer {
discoverAdapter.submitList(it)
})
invalidating datasource on refresh
Error Logs
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 20(offset:20).state:21 androidx.recyclerview.widget.RecyclerView{ecd9c90 VFED….. .F….ID 0,0-704,1024 #7f08021d app:id/rvPost}, adapter:com.app.ui.main.dashboard.search.discover.adapter.DiscoverAdapter@a9fb989, layout:androidx.recyclerview.widget.GridLayoutManager@97fed8e, context:[email protected]
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6183)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4085)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3849)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:625)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148)
at com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:43)
at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1892)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:918)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148)
at com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:43)
at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1892)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:918)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1743)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1586)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1495)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:336)
at android.widget.FrameLayout.onLayout(FrameLayout.java:273)
at android.view.View.layout(View.java:16651)
at android.view.ViewGroup.layout(ViewGroup.java:5440)
at androi
Comments
Comment posted by Arrowsome
If you provide your error log I would probably help you. I’ve been working on Android Paging Library for the last two weeks and also implemented Pull To Refresh. Provide your DataSource and LiveData setup for PagedList.
Comment posted by Amar Singh
please check question i resubmited error log
Comment posted by Lalit Fauzdar
It has nothing to do with
Comment posted by Amar Singh
im using paging adapter. and i think notify is not required in pagingadapter. livedata observer set data to recyclerview auto;
Comment posted by ahmed shaaban
please print your submitList method
Comment posted by ahmed shaaban
– livedata will observe when data change in your context in activity or fragment – livedata will submit list to your adapter – but list in adapter is different object list and adapter need to know that list has been changed so use notify data change method in adapter must be called you are fully understand of live data but what about adapter ? do u got it