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卡顿优化(二)附源码

点这里可以跳转到人工智能网站

发表评论