我将我的适配器移植到RecyclerView.Adapter
我想要实现的目标: 当用户向下滚动到最后我想开始获取数据时,我还想在最后添加i ProgressBar视图,让用户知道更多数据即将到来。
我在我的BaseAdapter中实现这个的方式:在getView
附近请求的视图中,我将开始获取更多数据,调用notifyDataSetChanged(以获取ProgressBar视图show)然后才返回getView
所需的视图。
我在RecyclerView.Adapter尝试做的事情:我试图基本上做同样的事情,这次是在方法onBindViewHolder
,
但如果我尝试在此方法中调用notifyItemInserted
,则会出现以下异常:
IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
我尝试了什么:我注意到onBindViewHolder
来自onLayoutChildren
来自LayoutManager
,我尝试覆盖它并在其notifyItemInserted
之后调用super
但我得到了同样的例外
我如何实现目标?
答案 0 :(得分:44)
Handler handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
};
handler.post(r);
我的示例代码,我调用adapter.notifyDataSetChanged();来自活动
答案 1 :(得分:20)
同样值得注意的是RecyclerView.isComputingLayout()
方法上的JavaDoc会触发此异常:
/**
* Returns whether RecyclerView is currently computing a layout.
* <p>
* If this method returns true, it means that RecyclerView is in a lockdown state and any
* attempt to update adapter contents will result in an exception because adapter contents
* cannot be changed while RecyclerView is trying to compute the layout.
* <p>
* It is very unlikely that your code will be running during this state as it is
* called by the framework when a layout traversal happens or RecyclerView starts to scroll
* in response to system events (touch, accessibility etc).
* <p>
* This case may happen if you have some custom logic to change adapter contents in
* response to a View callback (e.g. focus change callback) which might be triggered during a
* layout calculation. In these cases, you should just postpone the change using a Handler or a
* similar mechanism.
*
* @return <code>true</code> if RecyclerView is currently computing a layout, <code>false</code>
* otherwise
*/
public boolean isComputingLayout() {
return mLayoutOrScrollCounter > 0;
}
显着的短语是:
在这些情况下,您应该使用Handler或a来推迟更改 类似的机制。
在我的情况下,我正在修改另一个线程的适配器内容,这偶尔会导致冲突。将更新转移到UI线程上的处理程序自然可以解决这个问题。
答案 2 :(得分:9)
使用Handler
添加项目并从notify...()
调用Handler
为我解决了问题。
答案 3 :(得分:5)
整洁和轻松方式:
recyclerView.post(new Runnable() {
@Override
public void run() {
adapter.notifyDataSetChanged();
}
});
说明:您使用RecyclerView
实例并在post方法中添加了一个新的Runnable
消息队列。 runnable将在用户界面线程上运行。这是Android从后台访问UI线程的限制(例如,将在后台线程中运行的方法)。
答案 4 :(得分:1)
试试这个
if (!recyclerView.isComputingLayout()) {
recyclerView.notifyDataSetChanged();
}
答案 5 :(得分:0)
我用这个:
Handler handler = new Handler();
private void notifyItemInsertedEx(final int position) {
try {
notifyItemInserted(position);
} catch (Exception ex) {
handler.post(new Runnable(){
public void run(){
notifyItemInserted(position);
}
});
}
}