【Android】Glide结合Recyclerview(也适用于Listview)实现列表滑动的时候图片不加载,滑动停止的时候加载(已修正Listview部分以及排版)

很多人会问为什么要用 glide,其它的库可以么?其实只要图片库带有对应的方法都是可以的,只不过真心觉得这个库不错,就算是推荐吧。

然后着重讲 Recyclerview 是因为 Recyclerview 在 adapter 的onBindViewHolder 中对item的操作比较严格,如果处理操作比较多,耗时长(比如单个item的图片比较多)就会造成Recyclerview卡的现象(Listview 就没有这么严格),所以针对 Recyclerview 我们得进行特殊优化。

调出 glide 的方法,发现有两个方法:


Glide.with(context).resumeRequests();
Glide.with(context).pauseRequests();
根据方法名称不难理解:

其中第一个是恢复图片的请求加载,第二个是暂停图片的请求加载。

接下来我们就要看 Recyclerview(Listview同样)了,其中有一个 OnScrollListener ,这个就是对列表滑动的监听。

那么我们只要在滑动中和滑动停止这两种状态下对图片加载进行对应处理就可以了。

然后我们来看看 OnScrollListener 里面的两个方法:


onScrolled(RecyclerView recyclerView, int dx, int dy)
onScrollStateChanged(RecyclerView recyclerView, int newState)
其中我们需要关注第二个方法。第二个参数 newState 就是滑动的状态,有三个:


SCROLL_STATE_IDLE
SCROLL_STATE_DRAGGING
SCROLL_STATE_SETTLING
第一个英文解释是这样的:


The RecyclerView is not currently scrolling.
顾名思义,就是停止滑动。

第二个:


The RecyclerView is currently being dragged by outside input such as user touch input.
可以理解为:当屏幕滚动且用户使用的触碰或手指还在屏幕上。

第三个:


The RecyclerView is currently animating to a final position while not under outside control.
可以理解为:由于用户的操作,屏幕产生惯性滑动。

那么接下来我们只需要进行判断然后再调用 Glide 对应的方法就可以了,其中第一个状态要恢复图片请求加载,剩下的两个状态就要暂停图片请求加载。

最后提醒一下,因为 Recyclerview 大多都因项目需求而加入下拉刷新,上拉加载更多什么的,所以很多人引用了第三方改过的库,那么这个时候我们就可以通过改它的源码来实现我们的要求。

下面贴上代码:

public class XRecyclerView extends RecyclerView {
    public XRecyclerView(Context context) {
        this(context, null);
    }
 
    public XRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
 
    public XRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
 
    private void init() {
        addOnScrollListener(new ImageAutoLoadScrollListener());
    }
 
    //监听滚动来对图片加载进行判断处理
    public class ImageAutoLoadScrollListener extends OnScrollListener{
 
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }
 
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            switch (newState){
                case SCROLL_STATE_IDLE: // The RecyclerView is not currently scrolling.
                    //当屏幕停止滚动,加载图片
                    try {
                        if(getContext() != null) Glide.with(getContext()).resumeRequests();
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case SCROLL_STATE_DRAGGING: // The RecyclerView is currently being dragged by outside input such as user touch input.
                    //当屏幕滚动且用户使用的触碰或手指还在屏幕上,停止加载图片
                    try {
                        if(getContext() != null) Glide.with(getContext()).pauseRequests();
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case SCROLL_STATE_SETTLING: // The RecyclerView is currently animating to a final position while not under outside control.
                    //由于用户的操作,屏幕产生惯性滑动,停止加载图片
                    try {
                        if(getContext() != null) Glide.with(getContext()).pauseRequests();
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
    }
}

有人会问为什么要加上 try catch 呢,其实主要是为了避免一些情况下导致的崩溃(比如 context 已经销毁但不为 null 的情况),算是加上一层保险吧。


下面讲下 Listview 的:

Listview 的滑动状态跟 Recyclerview 的不太一样,同样有三个:

SCROLL_STATE_IDLE

SCROLL_STATE_FLING

SCROLL_STATE_TOUCH_SCROLL

其中第一个跟 Recyclerview 一样,滑动停止。

第二个照字面理解就是正在滚动。

至于第三个,网上的资料给的解释是手接触 Listview 会触动一次。

那么我们只需对前两个状态进行判断处理就可以了。

下面贴上 OnScrollStateChanged 部分的代码:


@Override
    public void onScrollStateChanged(AbsListView view, int newState) {
 
        switch (newState){
            case SCROLL_STATE_IDLE:
                //滑动停止
                try {
                    if(getContext() != null) Glide.with(getContext()).resumeRequests();
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case SCROLL_STATE_FLING:
                //正在滚动
                try {
                    if(getContext() != null) Glide.with(getContext()).pauseRequests();
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
                break;
 
        }
 
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中使用 RecyclerView 加载图片时,可以使用 Glide 库进行图片加载,同时可以通过以下几种方式进行滑动图片加载的优化: 1. 设置缓存策略:通过设置 Glide 的缓存策略,可以减少图片加载时的网络请求,提高加载速度。可以使用如下代码设置缓存策略: ``` RequestOptions requestOptions = new RequestOptions() .diskCacheStrategy(DiskCacheStrategy.ALL) .skipMemoryCache(false); Glide.with(context) .setDefaultRequestOptions(requestOptions) .load(url) .into(imageView); ``` 上述代码中,`diskCacheStrategy(DiskCacheStrategy.ALL)` 表示将图片缓存在磁盘中,`skipMemoryCache(false)` 表示不跳过内存缓存。 2. 设置占位符和错误图片:通过设置占位符和错误图片,可以在图片加载失败或者未加载完成时,显示一张默认的图片,避免出现空白的情况,同时也可以提高用户体验。可以使用如下代码设置占位符和错误图片: ``` RequestOptions requestOptions = new RequestOptions() .placeholder(R.drawable.placeholder) .error(R.drawable.error) .diskCacheStrategy(DiskCacheStrategy.ALL) .skipMemoryCache(false); Glide.with(context) .setDefaultRequestOptions(requestOptions) .load(url) .into(imageView); ``` 上述代码中,`placeholder(R.drawable.placeholder)` 表示在图片加载之前显示的占位符图片,`error(R.drawable.error)` 表示图片加载失败时显示的错误图片。 3. 取消加载任务:在 RecyclerView 滑动时,可能会存在用户滑动过快,导致部分图片加载完成,此时需要在滑动停止时,及时取消未完成的加载任务,避免加载任务过多,影响性能。可以使用如下代码取消加载任务: ``` @Override public void onViewDetachedFromWindow(@NonNull ViewHolder holder) { super.onViewDetachedFromWindow(holder); Glide.with(context).clear(holder.imageView); } ``` 上述代码中,`onViewDetachedFromWindow` 方法表示视图从窗口中移除时会被调用,通过 `Glide.with(context).clear(holder.imageView)` 取消当前视图中的加载任务。 通过上述优化方式,可以提高 RecyclerView 加载图片时的性能和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值