RecyclerView的卡顿优化(一)

对于列表,不管用RecyclerView 还是ListView,我们都会用ViewHolder来复用布局。但是,即使这样做了,还是会出现卡顿。

这时候我们就需要分析卡顿的原因是什么?为什么别人写的不卡?为什么很多商店的app都有卡顿?

卡顿的原因:

1.产品设计不合理导致卡片布局过度复杂,产品只追求界面的高大上,而忽略了实现上的复杂度。

2.卡顿的另一个最大原因是图片的加载,如果图片过大,卡顿甚至崩溃都不是问题。即使图片使用了压缩后的,并且用了Fresco等图片加载框架,发现还是会有卡顿。虽然图片是异步加载的,但是图片的加载都伴随着三级缓存,图片IO会导致卡

经过以上1,2分析,然后就开始考虑该怎么去优化呢?如果产品的需求改变不了,那就要另辟蹊径了。也就是主要的优化集中在复杂布局和图片加载。


复杂布局的优化:

1.尽量减少布局嵌套,层级越深,每次测量时间久越久。

2. 如果布局很复杂,可以考虑自定义布局能不能实现。

3.尽量减少过度绘制区域。这个可以在开发者选项中看到:调试GPU过度绘制。


图片加载的优化,不仅仅是图片加载,应该说是列表在滚动过程中,如果布局很复杂,而且样式也很多,那就需要考虑滚动的时候不做复杂布局及图片的加载,尽量减少滚动过程中的耗时操作,这样滚动停止的时候再加载可见区域的布局,因为这个时候是停止状态,即使略微耗时一些用户的感知也是比较小的,就会给人一种不卡的假象。


对于列表滚动过程中,卡顿的判断可以打开开发者选项中的:GPU呈现模式分析->在屏幕上显示为条形图。就可以直观的看到滑动过程中有没有卡顿了。


先上一些关键代码吧:

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;


/**
 * Created by lk on 16/7/12.
 */
public class PWRecyclerView extends RecyclerView {

    private OnScrolledLinstener onScrolledLinstener;
    private BaseAdapter adapter;
    private LayoutManager layout;

    public PWRecyclerView(Context context) {
        this(context, null);
    }

    public PWRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PWRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        addOnScrollListener(new ImageAutoLoadScrollListener());
    }

    @Override
    public void setLayoutManager(LayoutManager layout) {
        this.layout = layout;
        super.setLayoutManager(layout);
    }

    @Override
    public void setAdapter(Adapter adapter) {
        if(adapter instanceof BaseAdapter) {
            this.adapter = (BaseAdapter) adapter;
        }
        super.setAdapter(adapter);
    }

    public class ImageAutoLoadScrollListener extends OnScrollListener{

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if(onScrolledLinstener != null){
                onScrolledLinstener.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.
                    //对于滚动不加载图片的尝试
                    adapter.setScrolling(false);
                    adapter.notifyDataSetChanged();
                    break;
                case SCROLL_STATE_DRAGGING: // The RecyclerView is currently being dragged by outside input such as user touch input.
                    adapter.setScrolling(false);
                    break;
                case SCROLL_STATE_SETTLING: // The RecyclerView is currently animating to a final position while not under
                    adapter.setScrolling(true);
                    break;
            }
        }
    }


    public void setOnScrollLinstener(OnScrolledLinstener onScrolledLinstener){
        this.onScrolledLinstener = onScrolledLinstener;
    }

    public interface OnScrolledLinstener{
        void onScrolled(RecyclerView recyclerView, int dx, int dy);
    }



}

主要就是对onScrollStateChanged方法进行监听,然后通知adapter是否加载图片或复杂布局。


对于复杂布局的优化效果还是很明显的。


如果读者有更好的方法,请不吝赐教。


下面是基于此文进行的进一步优化

RecyclerView卡顿优化(二)附源码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值