我正在使用Recycler视图构建无限水平滚动列表。 屏幕上始终可以看到1-2个孩子(因为他们的宽度超过了屏幕视口,因此我们永远不会有超过2个孩子可见)。
当用户滚动时(他们可以向前和向后滚动 - 但是为了摇动这个例子,让我们假设他们正在滚动后退),我正在获取更多数据,而我m将它们添加到我的适配器数据中。
我正在调用notifyItemRangeInserted
- 到目前为止一直很好。
同时我添加了我检查的所有孩子,我们现在最终得到数据源中 MAX_DATASOURCE_CNT
个项目。
我们假设此示例中MAX_DATASOURCE_CNT
6 。
如果我们这样做,我会从数据源的末尾删除不必要的额外孩子,然后拨打notifyItemRangeRemoved
。
我这样做是因为我不想用未使用的数据充斥设备。我现在正在简化示例,但实际上我的视图可以在用户滚动时累积数千个未使用的数据项,并且我想动态修剪数据源的另一端。
在进行前置处理后,如果用户滚动太快,有时会onBindViewHolder(RecyclerView.ViewHolder holder, int position)
使用position == 0
(也是holder.getAdapterPosition() == 0
)来调用
这完全搞砸了我的观点,因为好像我的观点跳到一个完全无关紧要的孩子并且显示出那个。
我注意到如果我删除整个剪辑过程,基本上是这些代码行:
if (itemCountAfterPrepend > MAX_DATASOURCE_CNT) {
int extraItemCnt = itemCountAfterPrepend - MAX_DATASOURCE_CNT;
// remove every extra item from the end of the array
removeRange(MAX_DATASOURCE_CNT, itemCountAfterPrepend);
// and notify our adapter about the removal
notifyItemRangeRemoved(MAX_DATASOURCE_CNT, extraItemCnt);
}
一切正常。但我真的想削减我的数据。
我该怎么办?
谢谢
答案 0 :(得分:0)
好的,我没有找到具体的答案,所以反而是我的所作所为。
由于在绑定视图时问题是notifyItemRangeRemoved
正在运行,并且由于用户仍在滚动而绑定了视图,因此我从prepend / append函数中删除了剪切过程。
相反,我将剪辑过程设为独立函数(clipExtraDataIfNecessary
)。
此onScrollStateChanged(RecyclerView recyclerView, int newState)
仅在newState == SCROLL_STATE_IDLE
时调用,仅在/**
* make sure we never surpass the MAX_DATASOURCE_CNT limit
* Clips the data ArrayList from the ending (right) side
*/
public void clipExtraEndData() {
int itemCountAfterPrepend = this.data.size();
// if we went above our max data source count limit
if (itemCountAfterPrepend > MAX_DATASOURCE_CNT) {
int extraItemCnt = itemCountAfterPrepend - MAX_DATASOURCE_CNT;
synchronized (dataMutationLock) {
// remove every extra item from the end of the array
removeRange(MAX_DATASOURCE_CNT, itemCountAfterPrepend);
// and notify our adapter about the removal
notifyItemRangeRemoved(MAX_DATASOURCE_CNT, extraItemCnt);
}
}
}
/**
* make sure we never surpass the MAX_DATASOURCE_CNT limit
* Clips the data ArrayList from the beginning (left) side
*/
public void clipExtraStartData() {
int itemCountAfterAppend = this.data.size();
// if we went above our max data-source count limit
if (itemCountAfterAppend > MAX_DATASOURCE_CNT) {
int extraItemCnt = itemCountAfterAppend - MAX_DATASOURCE_CNT;
synchronized (dataMutationLock) {
// remove every extra item from the beginning of the array
removeRange(0, extraItemCnt);
// and notify our adapter about the removal
notifyItemRangeRemoved(0, extraItemCnt);
}
}
}
/**
* Removes all the extra data that we have accumulated by prepending/appending
* as the user was scrolling
*
* CAUTION: MAKE SURE YOU RUN THIS at a time where the user is NOT scrolling,
* otherwise we run the risk of bindViewRow being called with preLayout position
* values (a.k.a 0)
* @param curVisiblePosition
*/
public void clipExtraDataIfNecessary(int curVisiblePosition) {
int initialItemCnt = size();
if (initialItemCnt > MAX_DATASOURCE_CNT) {
if (curVisiblePosition < initialItemCnt - curVisiblePosition) {
// we have extra children on the end of our data
clipExtraEndData();
} else {
// we have extra children on the beginning of our data
clipExtraStartData();
}
}
}
时调用,即用户已停止滚动:
数据剪辑方法现在看起来像这样:
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_TAB);
robot.delay(100);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_ALT);