gpt4 book ai didi

android - Recyclerview - 无法在滚动回调中调用此方法

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:54:18 32 4
gpt4 key购买 nike

我在 StackOverflow 中多次看到这个问题,但我无法解决问题。于是伸出援手。

请注意:我已经检查过关于 SO 的其他问题,虽然我可以消除错误,但它还有其他问题。

这是我现有的代码:

我的适配器类:

  public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

Context context;

private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
private IOnLoadMoreListener mIOnLoadMoreListener;

private int visibleThreshold = 3;
private int lastVisibleItem, totalItemCount;
private int[] lastVisibleItems = new int[mStaggeredLayoutManager.getSpanCount()];

public RecyclerViewAdapter(Context context) {
this.context = context;

final StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);

totalItemCount = staggeredGridLayoutManager.getItemCount();
lastVisibleItems = staggeredGridLayoutManager.findLastVisibleItemPositions(new int[mStaggeredLayoutManager.getSpanCount()]);

if (staggeredGridLayoutManager.getSpanCount() == 1) {
lastVisibleItem = lastVisibleItems[0];
} else if (staggeredGridLayoutManager.getSpanCount() == 2) {
lastVisibleItem = Math.max(lastVisibleItems[0], lastVisibleItems[1]);
} else if (staggeredGridLayoutManager.getSpanCount() == 3) {
lastVisibleItem = Math.max(Math.max(lastVisibleItems[0], lastVisibleItems[1]), lastVisibleItems[2]);
}

if (!isRefreshing && totalItemCount <= lastVisibleItem + visibleThreshold) {

if (mIOnLoadMoreListener != null) {
mIOnLoadMoreListener.onLoadMore();
}

isRefreshing = true;
}
}
});

}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

if (viewType == VIEW_TYPE_ITEM) {

View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_recyclerview_shop_fragment, parent, false);
return new CustomViewHolder(v);
} else if (viewType == VIEW_TYPE_LOADING) {

View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_recyclerview_loading_shop_fragment, parent, false);
return new LoadingViewHolder(v);
}

return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

Product item = listItems.get(position);

if (holder.getItemViewType() == VIEW_TYPE_ITEM) {

CustomViewHolder customViewHolder = (CustomViewHolder) holder;
Glide.with(context).load(item.getFeaturedSrc()).into(customViewHolder.imageView);

} else if (holder.getItemViewType() == VIEW_TYPE_LOADING) {

if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
}


}

@Override
public int getItemCount() {
return listItems == null ? 0 : listItems.size();
}

@Override
public int getItemViewType(int position) {

if (listItems.get(position) == null) {
return VIEW_TYPE_LOADING;
} else {
return VIEW_TYPE_ITEM;
}
}

public void setOnLoadMoreListener(IOnLoadMoreListener mIOnLoadMoreListener) {
this.mIOnLoadMoreListener = mIOnLoadMoreListener;
}


public class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

ImageView imageView;
TextView textView;

String id;

public CustomViewHolder(View itemView) {
super(itemView);

itemView.setOnClickListener(this);
imageView = (ImageView) itemView.findViewById(R.id.imageView_thumbnail);

}

@Override
public void onClick(View v) {

int position = getAdapterPosition();

}
}

public class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;

public LoadingViewHolder(View progressView) {
super(progressView);
progressBar = (ProgressBar) progressView.findViewById(R.id.progressBar);
}
}

}

我以前的代码:

   mRecyclerViewAdapter.setOnLoadMoreListener(new IOnLoadMoreListener() {
@Override
public void onLoadMore() {

listItems.add(null);

mRecyclerViewAdapter.notifyItemChanged(listItems.size() - 1);
mRecyclerViewAdapter.notifyDataSetChanged();

isProgressVisible = true;

getDataFromServer(false);

}
});

使用我的旧代码,我得到以下 IllegalStateException:

W/RecyclerView: Cannot call this method in a scroll callback. Scroll callbacks mightbe run during a measure & layout pass where you cannot change theRecyclerView data. Any method call that might change the structureof the RecyclerView or the adapter contents should be postponed tothe next frame.
java.lang.IllegalStateException:

at android.support.v7.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:2581)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onItemRangeChanged(RecyclerView.java:4943)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyItemRangeChanged(RecyclerView.java:11373)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyItemRangeChanged(RecyclerView.java:11364)
at android.support.v7.widget.RecyclerView$Adapter.notifyItemChanged(RecyclerView.java:6652)
at codsiga.com.xx.ShopFragment$1.onLoadMore(ShopFragment.java:148)
at codsiga.com.xx.ShopFragment$RecyclerViewAdapter$1.onScrolled(ShopFragment.java:229)
at android.support.v7.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:4618)
at android.support.v7.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3679)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3323)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3844)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:636)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1795)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.support.design.widget.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:131)
at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1391)
at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:870)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1079)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1741)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1585)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1494)

03-22 11:36:32.083 3189-3189/codsiga.com.xx W/RecyclerView:
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:726)
at android.view.View.layout(View.java:17637)
at android.view.ViewGroup.layout(ViewGroup.java:5575)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2346)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2068)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
at android.view.Choreographer.doCallbacks(Choreographer.java:686)
at android.view.Choreographer.doFrame(Choreographer.java:621)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

因此,根据各种 StackOverflow 答案的建议,我将其修改如下:

查看各种答案的修改代码:

mRecyclerViewAdapter.setOnLoadMoreListener(new IOnLoadMoreListener() {
@Override
public void onLoadMore() {

recyclerView.post(new Runnable() {
@Override
public void run() {

listItems.add(null);

mRecyclerViewAdapter.notifyItemChanged(listItems.size() - 1);
mRecyclerViewAdapter.notifyDataSetChanged();

isProgressVisible = true;

getDataFromServer(false);


}
});
}
});

现在,我没有收到错误消息,但是 onLoadMore() 被调用了两次,每次都会刷新 recyclerview 中的 View 。我做错了什么?请查看 logcat 输出:

D/xx: Response => {…}
D/xx: Length = 9
D/xx: Query 'SELECT * FROM products' returned 9 rows

D/xx: Response => {…}
D/xx: Length = 9
D/xx: Query 'SELECT * FROM products' returned 18 rows

最佳答案

Cannot call this method in a scroll callback. Scroll callbacks mightbe run during a measure & layout pass where you cannot change theRecyclerView data. Any method call that might change the structureof the RecyclerView or the adapter contents should be postponed tothe next frame.

警告本身就是一种解释。 换句话说,您正在更新 View ,而 recyclerview 正在计算布局尺寸

哪里出了问题?下面的实现 -

mRecyclerViewAdapter.notifyItemChanged(listItems.size() - 1);
mRecyclerViewAdapter.notifyDataSetChanged();

您可以做的是将此 UI 操作发送到下一个 UI 框架。您可以通过调用 View.post() 方法来完成此操作。

recyclerView.post(new Runnable() {
public void run() {
// There is no need to use notifyDataSetChanged()
mRecyclerViewAdapter.notifyItemInserted(allArticles.size() - 1);
}
});

关于android - Recyclerview - 无法在滚动回调中调用此方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42944005/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com