BRVAH(让RecyclerView变得更高效)

作者: 吴小博Toby | 来源:发表于2017-09-18 14:33 被阅读6239次

    对于RecyclerView, 我们重复编写着那一个又一个的列表界面,有的要分组,有的要添加广告头部、有的要不同类型item排列、等等需求,主要代码有大部分是重复的,如果有一个框架能够帮快速的解决各种需求,那该多好。

    BRVAH是GitHub上一个强大的RecyclerAdapter框架,它能节约开发者大量的开发时间,它集成了大部分列表常用需求解决方案。 该框架于2016年4月10号发布,至今,经历了700多次迭代。

    presentation by吴思博

    github:https://github.com/CymChad/BaseRecyclerViewAdapterHelper

    official website:www.recyclerview.org

    Author(Brvah) blog:http://www.jianshu.com/u/f958e66439f0

    它能干

    解放你的双手,让你少码代码!

    列表、子布局

    一行代码轻松切换5种动画

    让你感觉又回到ListView时代!

    哼、列表需求来呀!

    来了什么好

    提高效率

    BRVAH是Github上的一个很棒的开源项目,主要作用是帮助我们更加高效的使用Recyclerview控件,处理项目中常见需求的Adapter,使用起来非常方便。

    BRVAH主要是针对Adapter来设计的,为我们提供了一般情况下的BaseQuickAdapter,和几个特定需求下的Adapter,BaseMultiItemQuickAdapter用于复杂类布局列表;BaseItemDraggableAdapter用于拖拽移动和滑动删除类列表;BaseSectionQuickAdapter用于带Section头部View的列表。

    一、框架引入:

    二、基本使用

    Activity代码:(和普通的一样)

    正常的adapter写法:

    onCreateViewHolder(这个方法主要生成为每个Item inflater出一个View,方法返回的是一个ViewHolder。 方法是把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,这个ViewHolder需要我们自己去编写。直接省去了当初Listview的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。)和onBindViewHolder(这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView)等方法。

    使用BRAVH的Adapter:

    首先需要继承BaseQuickAdapter,然后BaseQuickAdapter中第一个泛型T是数据实体类型,第二个BaseViewHolder是ViewHolder,其目的是为了支持扩展ViewHolder。

    可以通过viewHolder.getView(viewId)获取该控件。 通过viewHolder.getLayoutPosition()获取当前item的position。(为什么有数据不显示?检查一下的RecyclerView是否设置了LayoutManager。)

    代码量是3:1的比例!

    和原始的adapter相对,减少了70%的代码量。

    实现思路:

    找到重复部分代码,抽取到基类,非重复部分用抽象方法代替,具体让子类实现。具体代码BaseQuickAdapter如下:(onCreateViewHolder方法和普通adapter一样,对onBindViewHolder方法进行了提取,使用抽象方法convert(抽象方法)代替。)

    接下来再看看BaseViewHolder怎么写的:( 把ViewHolder进行了封装,利用了SparseArray,加快了查找已创建好控件的速度,没有创建再使用findviewbyId再存入SparseArray)

    三、强大的功能

    1.复杂布局实现(多布局)

    在实际应用中经常会遇到各种样式的列表、宫格和列表同时存在、分类列表等情况。

    1.1多布局

    在云阅读中的使用:“评论页面”(优点: 代码量少,节省时间,简洁,清晰,易维护)

    普通多布局写法:

    getItemViewType方法,根据位置获取当前item的类型,在onCreateViewHolder和onBindViewHolder中匹配类型进行操作。

    BRAVH是怎么实现?

    1、实体类(UserComment)实现MultiItemEntity接口,在设置数据的时候,给每一个数据设置itemType。

    评论的实体类:

    2、adapter继承BaseMultiItemQuickAdapter类,在构造方法中调用addItemType()方法加入定义的itemType和对应布局, 在Activity中实例化即可。

    和原始的adapter相对,减少70%的代码量,更加清晰易于维护。

    原理分析:

    1.2宫格和列表的混排样式

    关于Grid和List的混排样式,Grid样式是一行有多个,而List样式是一行只有一个。 我们可以把List样式看成是Grid样式,它就相当于把一个Grid的item拉长了的样子。

    列表与网格混排的布局效果,我们可以创建adapter继承BaseMultiItemQuickAdapter添加对应item类型的布局文件,也可以在Activity中创建GridLayoutManager对象,设置spanSize属性,通过Adapter的setSpanSizeLookup()方法设置每种item类型对应的spanSize。设置Recyclerview的addItemDecoration()方法设置添加分割线或设置item间距。

    在创建GridLayoutManager对象时,spanSize的参数需要设置,它的作用就是使原来一个item占满一行变为可以最多三个item占满一行。

    而设置setSpanSizeLookup()方法返回的是对应每种item类型返回具体的横跨大小。比如代码中TYPE_GRID类型的item在设置的spanSize是1,而GridLayoutManager设置的spanSize是3,那么该类型的item就会以3个item占满一行,相当于每个item占一行的1/3。

    代码片段:

    在我们使用addItemDecoration()添加分割线的方法中对这种混排的列表设置item间距的时候,在getItemOffsets()方法里,通过GridLayoutManager.LayoutParams获取spanSize来确定item类型设置对应间距, 其中spanIndex表示当前行item对应的下标位置,从左到右依次从0开始。

    1.3 Recyclerview嵌套Recyclerview的复杂布局

    我们“文学漫画”产品中,那些地方用到这种布局?例如蜗牛的领读ReadTrendFragment、Lofter发现音乐Fragment、 云阅读书店BookStoreFragment。

    蜗牛的领读ReadTrendFragmentLofter发现的音乐Fragment

    这种界面布局样式,最外面一个RecyclerView,它里面嵌套一个RecyclerView。继承BaseMultiItemQuickAdapter在重写的convert()方法中实例化子Recyclerview。

    需要注意的是Recyclerview嵌套Recyclerview会出现子Recyclerview抢焦点的问题, 导致界面顶部部分控件被挤出, 只需在最外面的Recyclerview的包裹容器中设置属性

    Android:descendantFocusability="blocksDescendants"即可。

    2.实现了点击监听事件

    BRVAH为我们提供好了全面的item和item子View的监听事件,我们只需在继承它提供的Adapter的基础上,通过adapter来调用对应的监听。 设置监听子View前,我们需要在adapter中对应的item的子View注册对应的监听事件。

    2.1对于item的监听事件处理

    直接在Activity中添加item点击事件,和listview一样。

    item长按监听事件

    2.2对item中子View的监听事件处理

    首先需要在adapter中,注册子View的监听事件。

    2.3也可以通过viewHolder.getView(viewId)获取该控件,再设置监听。

    3实现列表加载动画效果

    3.1默认动画

    我们只需将自建的adapter继承它对应满足需求的Adapter,然后在Activity中实例化,通过openLoadAnimation()方法完成特定的动画效果。

    BRVAH支持5种动画:

    渐显、缩放、从下到上,从左到右、从右到左

    3.2自定义动画

    我们也可以自定义动画,通过实现BaseAnimation这个类,重写

    getAnimators(View view)方法来完成自定义动画。

    3.3动画其他设置

    动画默认只执行一次,如果想重复执行可设置: mQuickAdapter.isFirstOnly(false);

    设置不显示动画数量:adapter.setNotDoAnimationCount(count);

    由于进入界面的item都是很多的速度进来的所以不会出现滑动显示的依次执行动画效果,这个时候会一起执行动画,如果觉得这样的效果不好可以使用setNotDoAnimationCount设置第一屏item不执行动画, 但是如果需要依次执行动画可以重写startAnim让第一个屏幕的item动画延迟执行即可。

    如何做到的?

    首先判断是否开启动画,然后判断是否是自定义动画还是用户选择的自带动画,然后对动画的操作元素进行遍历执行,执行时间为300毫秒,由于上面说了每次填充数据都会调用,所以如何不判断的话,就会导致上下滑动每次都会重复调用动画,动画本身是会耗费性能的。添加一个mLastPosition来存储滑动过的位置,然后判断滑动的位置是否被滑动过,这样就可以避免每次都添加动画了。不过为了满足喜欢动画多过于性能的开发者,如果你想要每次滑动都带动画可以设置isFirstOnly属性即可,默认是不开启的。

    4添加头部、尾部只需要一行代码。

    添加:

    删除指定view:

    删除所有:

    默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示:

    默认头部尾部都是占满一行,如果需要不占满可以配置:

    其中HeaderView和FooterView可以包含多个View,LoadingMoreView在BRVAH中固定成了一个。无论HeaderView里面包含了多少个Header,HeaderView会被整体当成一个Item,所以当Adapter需要刷新HeaderView的时候始终都是刷新position = 0的位置(同理,FooterView也是一个道理)

    这里需要重点理解的是HeaderView中Header的数量和RecycleView整个Item数量之间的关系,BRVAH中,HeaderView和FooterView都是LinerLayout,向这个LinerLayout中增加View是不影响RecycleView的ItemCount的。千万不要想当然的认为Add了几个Header然后ItemCount就会加几了。这点理解了源代码理解起来就很容易了

    5.实现Recyclerview刷新

    这个框架也帮我们实现了,下拉刷新,上拉加载等,傻瓜式实现。

    5.1上拉加载

    在按照BRVAH框架设置完adapter后,在Activity中让类实现BaseQuickAdapter.RequestLoadMoreListener接口,重写onLoadMoreRequested( )方法,在方法中调用mAdapter.addData()来添加新的数据,接着设置mAdapter.loadMoreComplete(),在数据都加载完后设置mAdapter.loadMoreEnd(false)显示数据加载完毕。

    默认第一次加载会进入回调,如果不需要可以配置:

    mQuickAdapter.disableLoadMoreIfNotFullPage();

    5.2设置自定义加载布局

    mQuickAdapter.setLoadMoreView(newCustomLoadMoreView());

    (注意:如果上拉结束后,下拉刷新需要再次开启上拉监听,需要使用setNewData方法填充数据。)

    5.3下拉刷新

    6.实现分组布局

    设置MySection类继承SectionEntity,创建不同的构造方法来设置item是否有header。 在adapter中,增加了convertHead()方法来加载head数据。在Activity中根据数据创建不同的MySection对象加入集合,设置给adapter。

    根据数据确定不同的样式,用不同的构造方法设置item布局。

    在adapter中,构造方法需要传入两个不同的布局id,第一个是item的layout id,第二个是head,item的数据加载在convert()方法中,head的数据加载在convertHead()方法中。

    7.设置空布局

    一行代码搞定。

    //没有数据的时候默认显示该布局

    mQuickAdapter.setEmptyView(getView());

    8.实现Recyclerview拖拽滑动删除

    添加RecyclerView的拖拽和滑动移除很简单,只需adapter继承BaseItemDraggableAdapter类,在Activity中,添加OnItemDragListener和OnItemSwipeListener两个接口,通过adapter配置基本属性即可。

    Activity使用代码:

    拖拽和滑动删除的回调方法

    adapter需要继承BaseItemDraggableAdapter

    默认不支持多个不同的ViewType之间进行拖拽,如果开发者有所需求:

    9自定义ViewHolder

    需要继承BaseViewHolder

    publicclassMovieViewHolderextendsBaseViewHolder

    然后修改adapter的第二个泛型为自定义的ViewHolder

    publicclassDataBindingUseAdapterextendsBaseQuickAdapter

    注意:需要单独建一个外部类继承BaseViewHolder,否则部分机型会出现ClassCastException,如果是内部类的构造方法要是public,定义的那个类也最好是public。

    10添加data方法

    11其它

    树形列表,查看官方网站

    四、总结

    找到重复部分代码,抽取到基类,非重复部分用抽象方法代替,具体让子类实现。提高了代码复用率, 减少了代码量, 轻松添加各种点击事件,多布局, 一行代码添加加载动画效果,添加头部、尾部、下拉刷新、上拉加载、让你感觉又回到ListView时代! 最重要的是在我们“文学漫画”产品中也可以很好的接入。

    Thank you!!

    相关文章

      网友评论

        本文标题:BRVAH(让RecyclerView变得更高效)

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