美文网首页
recycleview滑动优化

recycleview滑动优化

作者: couriravant | 来源:发表于2019-12-22 19:59 被阅读0次

    1、recyclerView.setHasFixedSize(true);
    当Item的高度如是固定的,设置这个属性为true可以提高性能,尤其是当RecyclerView有条目插入、删除时性能提升更明显。RecyclerView在条目数量改变,会重新测量、布局各个item,如果设置了setHasFixedSize(true),由于item的宽高都是固定的,adapter的内容改变时,RecyclerView不会整个布局都重绘。具体可用以下伪代码表示:

    void onItemsInsertedOrRemoved() {
       if (hasFixedSize) layoutChildren();
       else requestLayout();
    }
    

    2、使用getExtraLayoutSpace为LayoutManager设置更多的预留空间

    在RecyclerView的元素比较高,一屏只能显示一个元素的时候,第一次滑动到第二个元素会卡顿。

    如何解决这个问题呢,其实只需重写getExtraLayoutSpace()方法。根据官方文档的描述 getExtraLayoutSpace将返回LayoutManager应该预留的额外空间(显示范围之外,应该额外缓存的空间)。

    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this) {
        @Override
        protected int getExtraLayoutSpace(RecyclerView.State state) {
            return 300;
        }
    };
    

    4、避免创建过多对象
    onCreateViewHolder 和 onBindViewHolder 对时间都比较敏感,尽量避免繁琐的操作和循环创建对象。例如创建 OnClickListener,可以全局创建一个。同时onBindViewHolder调用次数会多于onCreateViewHolder的次数,如从RecyclerViewPool缓存池中取到的View都需要重新bindView,所以我们可以把监听放到CreateView中进行。

    优化前:

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
             //do something
           }
        });
    }
    

    优化后:

    private class XXXHolder extends RecyclerView.ViewHolder {
            private EditText mEt;
            EditHolder(View itemView) {
                super(itemView);
                mEt = (EditText) itemView;
                mEt.setOnClickListener(mOnClickListener);
            }
        }
        private View.OnClickListener mOnClickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //do something
            }
        }
    

    5、局部刷新
    可以用一下一些方法,替代notifyDataSetChanged,达到局部刷新的目的。notifyDataSetChanged会触发所有item的detached回调再触发onAttached回调。

    notifyItemChanged(int position)
    notifyItemInserted(int position)
    notifyItemRemoved(int position)
    notifyItemMoved(int fromPosition, int toPosition)
    notifyItemRangeChanged(int positionStart, int itemCount)
    notifyItemRangeInserted(int positionStart, int itemCount)
    notifyItemRangeRemoved(int positionStart, int itemCount)
    如果必须用 notifyDataSetChanged(),那么最好设置 mAdapter.setHasStableIds(true)
    DiffUtil是support包下新增的一个工具类,用来判断新数据和旧数据的差别,从而进行局部刷新。

    DiffUtil的使用,在原来调用mAdapter.notifyDataSetChanged()的地方:

    // mAdapter.notifyDataSetChanged()
    DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallBack(oldDatas, newDatas), true);
    diffResult.dispatchUpdatesTo(mAdapter);
    DiffUtil最终是调用Adapter的下面几个方法来进行局部刷新:

    mAdapter.notifyItemRangeInserted(position, count);
    mAdapter.notifyItemRangeRemoved(position, count);
    mAdapter.notifyItemMoved(fromPosition, toPosition);
    mAdapter.notifyItemRangeChanged(position, count, payload);

    6、重写onScroll事件
    对于大量图片的RecyclerView,滑动暂停后再加载;RecyclerView中存在几种绘制复杂,占用内存高的楼层类型,但是用户只是快速滑动到底部,并没有必要绘制计算这几种复杂类型,所以也可以考虑对滑动速度,滑动状态进行判断,满足条件后再加载这几种复杂的。
    7、RecyclerView缓存
    7.1 setItemViewCacheSize(int )
    RecyclerView可以设置自己所需要的ViewHolder缓存数量,默认大小是2。cacheViews中的缓存只能position相同才可得用,且不会重新bindView,CacheViews满了后移除到RecyclerPool中,并重置ViewHolder,如果对于可能来回滑动的RecyclerView,把CacheViews的缓存数量设置大一些,可以减少bindView的时间,加快布局显示。

    注:此方法是拿空间换时间,要充分考虑应用内存问题,根据应用实际使用情况设置大小。

    网上大部分设置CacheView大小时都会带上:

    setDrawingCacheEnabled(true)和setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)

    setDrawingCacheEnabled这个是View本身的方法,意途是开启缓存。通过setDrawingCacheEnabled把cache打开,再调用getDrawingCache就可以获得view的cache图片,如果cache没有建立,系统会自动调用buildDrawingCache方法来生成cache。一般截图会用到,这里的设置drawingcache,可能是在重绘时不需要重新计算bitmap的宽高等,能加快dispatchDraw的速度,但开启drawingcache,肯定也会耗应用的内存,所以也慎用。

    7.2 复用RecycledViewPool
    在TabLayout+ViewPager+RecyclerView的场景中,当多个RecyclerView有相同的item布局结构时,多个RecyclerView共用一个RecycledViewPool可以避免创建ViewHolder的开销,避免GC。RecycledViewPool对象可通过RecyclerView对象获取,也可以自己实现。

    RecycledViewPool mPool = mRecyclerView1.getRecycledViewPool();
    下一个RecyclerView可直接进行setRecycledViewPool

    mRecyclerView2.setRecycledViewPool(mPool);

    mRecyclerView3.setRecycledViewPool(mPool);

    相关文章

      网友评论

          本文标题:recycleview滑动优化

          本文链接:https://www.haomeiwen.com/subject/lfnonctx.html