上一篇 RecyclerView 卡顿优化(一)主要介绍了基本的优化思路及简单代码,对于布局不太复杂,基本够用了。
此篇主要介绍在上一篇的基础上,进行的进一步优化,及最后提供一个Demo(RecyclerView + 下拉刷新 + 上拉加载 + 滚动不加载优化)。
上一篇介绍到监听RecyclerView的OnScrollListener的onScrollStateChanged方法进行监听,当滚动停止时,刷新界面,实现加载。
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
(TAG, "stated:" + newState + " time:" + ());
switch (newState){
case RecyclerView.SCROLL_STATE_IDLE: // The RecyclerView is not currently scrolling.
scroll_count ++;
// ("scroll_state", "state:" + "停止");
if(() && scrlled) {
//对于滚动不加载图片的尝试
(false);
();
}
scrlled = false;
break;
case RecyclerView.SCROLL_STATE_DRAGGING: // The RecyclerView is currently being dragged by outside input such as user touch input.
// (false);
// ("scroll_state", "state:" + "拖拽");
break;
case RecyclerView.SCROLL_STATE_SETTLING: // The RecyclerView is currently animating to a final position while not under
// (true);
// ("scroll_state", "state:" + "滚动到某地");
break;
}
(recyclerView, newState);
}
这一点的优点很明显,不需要对当前屏幕显示的ViewHoler进行手动加载,直接交给()方法来刷新即可。
但是,缺点也很明显,就是用户稍微滚动一下界面,就要刷新一次,这样做在用户体验及交互上会有一定问题。
因此,就要考虑加载及不加载的时机。
优化前:列表只要滚动停止就加载,不管用户滚动了多少,不管是否快速滚动。
思路:
1.能否检测是不是快速滚动,只有快速滚动中不加载图片及复杂布局。
2.滚动停止时,判断是否存在图片或布局未加载,如果有,才加载。否则,不做任何操作。
3.如何判断快速滚动?
对于快速滚动的监听,方法有很多,比如列表滚动中计算一下滚动速度,如果速度大于某个值,我们就认为是快速滚动。
优化过程:
1.之前一直没有用过的监听,所以就尝试用了此方法。
public interface OnGestureListener {
boolean onDown(MotionEvent var1);
void onShowPress(MotionEvent var1);
boolean onSingleTapUp(MotionEvent var1);
boolean onScroll(MotionEvent var1, MotionEvent var2, float var3, float var4);
void onLongPress(MotionEvent var1);
boolean onFling(MotionEvent var1, MotionEvent var2, float var3, float var4);
}
@Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
(TAG, "onFling: " + (v1));
if((v1) > 4000){
(true);
}
return false;
}
v是x方向滑动速度,v1是y方向滑动速度。
选择(v1) > 4000来作为快速滑动的判断原因,自己测出来的。。。这个可以自己测试来定,一般快速滑动时,v1的值在4000+。
所以就解决了我们的第一个问题,快速滑动的监听,如果是快速滑动,就不加载图片。
2.通过判断()是否为true,来判断是不是有未加载图片。
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
(TAG, "stated:" + newState + " time:" + ());
switch (newState){
case RecyclerView.SCROLL_STATE_IDLE: // The RecyclerView is not currently scrolling.
scroll_count ++;
// ("scroll_state", "state:" + "停止");
if(() && scrlled) {
//对于滚动不加载图片的尝试
(false);
();
}
scrlled = false;
break;
case RecyclerView.SCROLL_STATE_DRAGGING: // The RecyclerView is currently being dragged by outside input such as user touch input.
// (false);
// ("scroll_state", "state:" + "拖拽");
break;
case RecyclerView.SCROLL_STATE_SETTLING: // The RecyclerView is currently animating to a final position while not under
// (true);
// ("scroll_state", "state:" + "滚动到某地");
break;
}
(recyclerView, newState);
}
3.细心的读者,可以发现多一个scrolled条件判断。
if(() && <span style="color:#ff0000;">scrlled</span>) {
//对于滚动不加载图片的尝试
(false);
();
}
scrolled是用来判断列表有没有发生滚动位移。
判断的地方RecyclerView的OnScrollListener的onScrolled方法:
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
(recyclerView, dx, dy);
<span style="color:#ff0000;"> if(dy != 0){
scrlled = true;
}</span>
}
为什么要加这个判断条件?
这是为了解决一个bug,如果列表在顶部或者底部,如果快速的在屏幕上向下或向上滑动,onFling可以监听到v1大于4000,并且onScrollStateChanged的RecyclerView.SCROLL_STATE_IDLE也会有监听,所以加一个额外条件,如果列表没有任何滚动,则不做任何操作。
git源码:RefreshRecyclerView
介绍文章:RefreshRecyclerView下拉刷新上拉加载