BaseQuickAdapter之BRVAH官方使用指南(持续更新)
![](http://upload-images.jianshu.io/upload_images/972352-9911637db5512613.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1000/format/webp)
官方网站:www.recyclerview.org
BRVAH是一个强大的RecyclerAdapter框架(什么是RecyclerView?),它能节约开发者大量的开发时间,集成了大部分列表常用需求解决方案。为什么会有它?请查看「Android开源框架BRVAH由来篇」该框架于2016年4月10号发布的第1个版本到现在已经一年多了,经历了800多次代码提交,140多次版本打包,修复了1000多个问题,获得了9000多star,非常感谢大家的使用以及反馈。
本篇为BRVAH的使用指南以及包含常见问题会第一时间更新最新的使用方法。最新版本请查看releases,由于持续更新。
文章目录
- 框架引入
- 优化Adapter代码
和原始的adapter相对,减少70%的代码量。 - 添加Item事件
Item的点击事件
Item的长按事件
Item子控件的点击事件
Item子控件的长按事件 - 添加列表加载动画
一行代码轻松切换5种默认动画。 - 添加头部、尾部
一行代码搞定,感觉又回到ListView时代。 - 自动加载
上拉加载无需监听滑动事件,可自定义加载布局,显示异常提示,自定义异常提示。同时支持下拉加载。 - 分组布局
随心定义分组头部。 - 多布局
简单配置、无需重写额外方法。 - 设置空布局
比Listview的setEmptyView还要好用。 - 添加拖拽、滑动删除
开启,监听即可,就是这么简单。 - 树形列表
比ExpandableListView还要强大,支持多级。 - 自定义ViewHolder
支持自定义ViewHolder,让开发者随心所欲。 - 扩展框架
组合第三方框架,轻松实现更多需求定制。
框架引入
先在 build.gradle(Project:XXXX) 的 repositories 添加:
allprojects {repositories {...maven { url "https://jitpack.io" }}}
然后在 build.gradle(Module:app) 的 dependencies 添加:
dependencies {compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'}
更新说明:https://github.com/CymChad/BaseRecyclerViewAdapterHelper/releases
注意
版本:2.9.28
Change the method setVisible --> setGone
The new method setVisible
setVisible:Set a view visibility to VISIBLE (true) or INVISIBLE (false).
setGone: Set a view visibility to VISIBLE (true) or GONE (false).
注意: 一旦出现加载失败的情况,只有两种情况:
- 配置没配置好
配置没配置好,有几种情况:
1. 只配置了dependencies
2. 配置repositories,但是位置错了,build.gradle(Project:XXXX) 文件下的repositories有两个,一个是buildscript下面的,一个是allprojects下面的,要配置到allprojects下面才是对的。
3. 版本号前面多一个v,这个是我的锅,在2.1.2版本之前都是带v的,之后(包含2.1.2)都不需要带v。 - 网络原因(这个就不解释了)
使用Adapter
和原始的adapter相对,减少70%的代码量。
![](http://upload-images.jianshu.io/upload_images/972352-bbacc52dd247f621.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
使用代码
public class HomeAdapter extends BaseQuickAdapter<HomeItem, BaseViewHolder> {public HomeAdapter(int layoutResId, List data) {super(layoutResId, data);}@Overrideprotected void convert(BaseViewHolder helper, HomeItem item) {helper.setText(R.id.text, item.getTitle());helper.setImageResource(R.id.icon, item.getImageResource());// 加载网络图片Glide.with(mContext).load(item.getUserAvatar()).crossFade().into((ImageView) helper.getView(R.id.iv));}
}
注:如果想深入了解的原理可以查看RecyclerView.Adapter优化了吗?
使用
首先需要继承BaseQuickAdapter
,然后BaseQuickAdapter<Status, BaseViewHolder>
第一个泛型Status
是数据实体类型,第二个BaseViewHolder
是ViewHolder其目的是为了支持扩展ViewHolder。
赋值
可以直接使用viewHolder
对象点相关方法通过传入viewId和数据进行,方法支持链式调用。如果是加载网络图片或自定义view可以通过viewHolder.getView(viewId)
获取该控件。
常用方法
- viewHolder.getLayoutPosition() 获取当前item的position
常见问题
这些问题不是使用该库的问题,但是经常有人问这些问题,所以特意写出来,帮助后续遇到以下问题的开发者们。
为什么有数据不显示?
请检查一下你的RecyclerView是否设置了LayoutManager。
为什么有10条数据,只显示1条?
请检查一下item的布局最外层的Layout是不是layout_height
设置了match_parent
.
数据状态错乱
这个问题无论是RecyclerView还是ListView不做处理都会出现问题,这个本质上是由于布局重用机制导致的,解决办法是通过数据状态来控制控件的状态,一定要设置状态无论什么状态,if
和else
是少不了的,如下代码:
if(entity.isCheck){checkBox.isChecked(true);} else {checkBox.isChecked(false);}
解决缓存问题案例:
- 处理文本框和单选的缓存问题
- 实现三级伸缩,并解决多选框的复用
添加Item事件
![](http://upload-images.jianshu.io/upload_images/972352-2782db0d3f5a85d6.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
Item的点击事件
adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {@Overridepublic void onItemClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemClick: ");Toast.makeText(ItemClickActivity.this, "onItemClick" + position, Toast.LENGTH_SHORT).show();}});
Item的长按事件
adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {@Overridepublic boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemLongClick: ");Toast.makeText(ItemClickActivity.this, "onItemLongClick" + position, Toast.LENGTH_SHORT).show();return false;}});
注意:嵌套recycleView的情况下需要使用你使用 adapter. setOnItemClickListener 来设置点击事件,如果使用recycleView.addOnItemTouchListener会累计添加的。
Item子控件的点击事件
首先在adapter的convert方法里面通过viewHolder.addOnClickListener
绑定一下的控件id
@Overrideprotected void convert(BaseViewHolder viewHolder, Status item) {viewHolder.setText(R.id.tweetName, item.getUserName()).setText(R.id.tweetText, item.getText()).setText(R.id.tweetDate, item.getCreatedAt()).setVisible(R.id.tweetRT, item.isRetweet()).addOnClickListener(R.id.tweetAvatar).addOnClickListener(R.id.tweetName).linkify(R.id.tweetText);
}
然后在设置
adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {@Overridepublic boolean onItemChildClick(BaseQuickAdapter adapter, View view, int position) {Log.d(TAG, "onItemChildClick: ");Toast.makeText(ItemClickActivity.this, "onItemChildClick" + position, Toast.LENGTH_SHORT).show();return false;}});
Item子控件的长按事件
步骤同上使用方法不同。
adapter中绑定方法将addOnClickListener
改成addOnLongClickListener
.
设置点击事件方法setOnItemChildClickListener
改成setOnItemChildLongClickListener
注意:设置子控件的事件,如果不在adapter中绑定,点击事件无法生效,因为无法找到你需要设置的控件。
如果需要在点击事件中获取其他子控件可以使用:
getViewByPosition(RecyclerView recyclerView, int position, @IdRes int viewId)
注意:如果有header的话需要处理一下position加上 headerlayoutcount。
添加列表加载动画
![](http://upload-images.jianshu.io/upload_images/972352-fda353fc3d9f67d7.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
开启动画(默认为渐显效果)
adapter.openLoadAnimation();
默认提供5种方法(渐显、缩放、从下到上,从左到右、从右到左)
public static final int ALPHAIN = 0x00000001;/*** Use with {@link #openLoadAnimation}*/public static final int SCALEIN = 0x00000002;/*** Use with {@link #openLoadAnimation}*/public static final int SLIDEIN_BOTTOM = 0x00000003;/*** Use with {@link #openLoadAnimation}*/public static final int SLIDEIN_LEFT = 0x00000004;/*** Use with {@link #openLoadAnimation}*/public static final int SLIDEIN_RIGHT = 0x00000005;
切换动画
quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);
自定义动画
quickAdapter.openLoadAnimation(new BaseAnimation() {@Overridepublic Animator[] getAnimators(View view) {return new Animator[]{ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)};}});
动画默认只执行一次,如果想重复执行可设置
mQuickAdapter.isFirstOnly(false);
注:如果想深入了解的原理可以查看BaseRecyclerAdapter之添加动画(策略模式)
设置不显示动画数量
adapter.setNotDoAnimationCount(count);
首次到界面的item都依次执行加载动画
由于进入界面的item都是很多的速度进来的所以不会出现滑动显示的依次执行动画效果,这个时候会一起执行动画,如果觉得这样的效果不好可以使用
setNotDoAnimationCount
设置第一屏item不执行动画,但是如果需要依次执行动画可以重写startAnim
让第一个屏幕的item动画延迟执行即可。
@Overrideprotected void startAnim(Animator anim, int index) {super.startAnim(anim, index);if (index < count)anim.setStartDelay(index * 150);}
添加头部、尾部
![](http://upload-images.jianshu.io/upload_images/972352-ef9eb5bc94c8b165.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
添加
mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());
注:如果想深入了解的原理可以查看BaseRecyclerAdapter之添加不同布局(头部尾部)
删除指定view
mQuickAdapter.removeHeaderView(getView);
mQuickAdapter.removeFooterView(getView);
删除所有
mQuickAdapter.removeAllHeaderView();
mQuickAdapter.removeAllFooterView();
默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示:
setHeaderAndEmpty
setHeaderFooterEmpty
默认头部尾部都是占满一行,如果需要不占满可以配置:
setHeaderViewAsFlow
setFooterViewAsFlow
自动加载
上拉加载
![](http://upload-images.jianshu.io/upload_images/972352-a06197a4e0aca2b7.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
// 滑动最后一个Item的时候回调onLoadMoreRequested方法
setOnLoadMoreListener(RequestLoadMoreListener);
默认第一次加载会进入回调,如果不需要可以配置:
mQuickAdapter.disableLoadMoreIfNotFullPage();
回调处理代码
mQuickAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {@Override public void onLoadMoreRequested() {mRecyclerView.postDelayed(new Runnable() {@Overridepublic void run() {if (mCurrentCounter >= TOTAL_COUNTER) {//数据全部加载完毕mQuickAdapter.loadMoreEnd();} else {if (isErr) {//成功获取更多数据mQuickAdapter.addData(DataServer.getSampleData(PAGE_SIZE));mCurrentCounter = mQuickAdapter.getData().size();mQuickAdapter.loadMoreComplete();} else {//获取更多数据失败isErr = true;Toast.makeText(PullToRefreshUseActivity.this, R.string.network_err, Toast.LENGTH_LONG).show();mQuickAdapter.loadMoreFail();
}}}}, delayMillis);}}, mReyclerView);
加载完成(注意不是加载结束,而是本次数据加载结束并且还有下页数据)
mQuickAdapter.loadMoreComplete();
加载失败
mQuickAdapter.loadMoreFail();
加载结束
mQuickAdapter.loadMoreEnd();
注意:如果上拉结束后,下拉刷新需要再次开启上拉监听,需要使用setNewData
方法填充数据。
打开或关闭加载(一般用于下拉的时候做处理,因为上拉下拉不能同时操作)
mQuickAdapter.setEnableLoadMore(boolean);
预加载
// 当列表滑动到倒数第N个Item的时候(默认是1)回调onLoadMoreRequested方法
mQuickAdapter.setPreLoadNumber(int);
设置自定义加载布局
mQuickAdapter.setLoadMoreView(new CustomLoadMoreView());
public final class CustomLoadMoreView extends LoadMoreView {@Override public int getLayoutId() {return R.layout.view_load_more;}/*** 如果返回true,数据全部加载完毕后会隐藏加载更多* 如果返回false,数据全部加载完毕后会显示getLoadEndViewId()布局*/@Override public boolean isLoadEndGone() {return true;}@Override protected int getLoadingViewId() {return R.id.load_more_loading_view;}@Override protected int getLoadFailViewId() {return R.id.load_more_load_fail_view;}/*** isLoadEndGone()为true,可以返回0* isLoadEndGone()为false,不能返回0*/@Override protected int getLoadEndViewId() {return 0;}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="@dimen/dp_40">
<span class="hljs-tag"><<span class="hljs-name">LinearLayout</span><span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/load_more_loading_view"</span><span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"match_parent"</span><span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"match_parent"</span><span class="hljs-attr">android:gravity</span>=<span class="hljs-string">"center"</span><span class="hljs-attr">android:orientation</span>=<span class="hljs-string">"horizontal"</span>></span><span class="hljs-tag"><<span class="hljs-name">ProgressBar</span><span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/loading_progress"</span><span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">style</span>=<span class="hljs-string">"?android:attr/progressBarStyleSmall"</span><span class="hljs-attr">android:layout_marginRight</span>=<span class="hljs-string">"@dimen/dp_4"</span><span class="hljs-attr">android:indeterminateDrawable</span>=<span class="hljs-string">"@drawable/sample_footer_loading_progress"</span>/></span><span class="hljs-tag"><<span class="hljs-name">TextView</span><span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/loading_text"</span><span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">android:layout_marginLeft</span>=<span class="hljs-string">"@dimen/dp_4"</span><span class="hljs-attr">android:text</span>=<span class="hljs-string">"@string/loading"</span><span class="hljs-attr">android:textColor</span>=<span class="hljs-string">"#0dddb8"</span><span class="hljs-attr">android:textSize</span>=<span class="hljs-string">"@dimen/sp_14"</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">LinearLayout</span>></span><span class="hljs-tag"><<span class="hljs-name">FrameLayout</span><span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/load_more_load_fail_view"</span><span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"match_parent"</span><span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"match_parent"</span><span class="hljs-attr">android:visibility</span>=<span class="hljs-string">"gone"</span>></span><span class="hljs-tag"><<span class="hljs-name">TextView</span><span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/tv_prompt"</span><span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span><span class="hljs-attr">android:layout_gravity</span>=<span class="hljs-string">"center"</span><span class="hljs-attr">android:textColor</span>=<span class="hljs-string">"#0dddb8"</span><span class="hljs-attr">android:text</span>=<span class="hljs-string">"@string/load_failed"</span>/></span><span class="hljs-tag"></<span class="hljs-name">FrameLayout</span>></span>
</FrameLayout>
下拉加载(符合聊天软件下拉历史数据需求)
![](http://upload-images.jianshu.io/upload_images/972352-94bb55810befcb5b.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
设置开启开关
mAdapter.setUpFetchEnable(true);
设置监听
mAdapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {@Overridepublic void onUpFetch() {startUpFetch();}});
private void startUpFetch() {count++;/*** set fetching on when start network request.*/mAdapter.setUpFetching(true);/*** get data from internet.*/mRecyclerView.postDelayed(new Runnable() {@Overridepublic void run() {mAdapter.addData(0, genData());/*** set fetching off when network request ends.*/mAdapter.setUpFetching(false);/*** set fetch enable false when you don't need anymore.*/if (count > 5) {mAdapter.setUpFetchEnable(false);}}}, 300);}
开始加载的位置
mAdapter.setStartUpFetchPosition(2);
分组布局
实体类必须继承SectionEntity
public class MySection extends SectionEntity<Video> {private boolean isMore;public MySection(boolean isHeader, String header) {super(isHeader, header);}public MySection(Video t) {super(t);}
}
adapter构造需要传入两个布局id,第一个是item的,第二个是head的,在convert
方法里面加载item数据,在convertHead
方法里面加载head数据
public class SectionAdapter extends BaseSectionQuickAdapter<MySection> {public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {super(layoutResId, sectionHeadResId, data);}@Overrideprotected void convert(BaseViewHolder helper, MySection item) {helper.setImageUrl(R.id.iv, (String) item.t);}@Overrideprotected void convertHead(BaseViewHolder helper,final MySection item) {helper.setText(R.id.header, item.header);helper.setOnClickListener(R.id.more, new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show();}});}
多布局
![](http://upload-images.jianshu.io/upload_images/972352-aa122442f6568954.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
实体类必须实现MultiItemEntity
,在设置数据的时候,需要给每一个数据设置itemType
public class MultipleItem implements MultiItemEntity {public static final int TEXT = 1;public static final int IMG = 2;private int itemType;public MultipleItem(int itemType) {this.itemType = itemType;}@Overridepublic int getItemType() {return itemType;}
}
在构造里面addItemType
绑定type和layout的关系
public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleItem, BaseViewHolder> {public MultipleItemQuickAdapter(List data) {super(data);addItemType(MultipleItem.TEXT, R.layout.text_view);addItemType(MultipleItem.IMG, R.layout.image_view);}@Overrideprotected void convert(BaseViewHolder helper, MultipleItem item) {switch (helper.getItemViewType()) {case MultipleItem.TEXT:helper.setImageUrl(R.id.tv, item.getContent());break;case MultipleItem.IMG:helper.setImageUrl(R.id.iv, item.getContent());break;}}
}
注:如果想深入了解的原理可以查看BaseRecyclerAdapter之添加不同布局(优化篇)
如果考虑到在GridLayoutManager
复用item问题可以配置:
multipleItemAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {@Overridepublic int getSpanSize(GridLayoutManager gridLayoutManager, int position) {return data.get(position).getSpanSize();}});
如果大家觉得这种多布局方式有点由于耦合了实体类,还有支持另外一种多布局方式具体可查看更便捷的多布局, 为 BaseQuickAdapter 设置代理.
如果使用多布局出现这个NotFoundException异常,有可能是addItemType()两个参数写反了。
设置空布局
![](http://upload-images.jianshu.io/upload_images/972352-0f4c2ff4ba11865f.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/341/format/webp)
// 没有数据的时候默认显示该布局
mQuickAdapter.setEmptyView(getView());
如果用网格布局的话,设置空布局就不能给全屏,可以使用瀑布流布局。
添加拖拽、滑动删除
拖拽和滑动删除的回调方法
OnItemDragListener onItemDragListener = new OnItemDragListener() {@Overridepublic void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){}@Overridepublic void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {}@Overridepublic void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {}
}
OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {@Overridepublic void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {}@Overridepublic void clearView(RecyclerView.ViewHolder viewHolder, int pos) {}@Overridepublic void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {}
};
adapter需要继承BaseItemDraggableAdapter
public class ItemDragAdapter extends BaseItemDraggableAdapter<String, BaseViewHolder> {public ItemDragAdapter(List data) {super(R.layout.item_draggable_view, data);}@Overrideprotected void convert(BaseViewHolder helper, String item) {helper.setText(R.id.tv, item);}
}
Activity使用代码
mAdapter = new ItemDragAdapter(mData);
ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
// 开启拖拽
mAdapter.enableDragItem(itemTouchHelper, R.id.textView, true);
mAdapter.setOnItemDragListener(onItemDragListener);
// 开启滑动删除
mAdapter.enableSwipeItem();
mAdapter.setOnItemSwipeListener(onItemSwipeListener);
默认不支持多个不同的 ViewType 之间进行拖拽,如果开发者有所需求:
重写
ItemDragAndSwipeCallback
里的onMove()
方法,return true
即可
树形列表
例子:三级菜单
// if you don't want to extent a class, you can also use the interface IExpandable.
// AbstractExpandableItem is just a helper class.
public class Level0Item extends AbstractExpandableItem<Level1Item> {...}
public class Level1Item extends AbstractExpandableItem<Person> {...}
public class Person {...}
adapter需要继承BaseMultiItemQuickAdapter
public class ExpandableItemAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> { public ExpandableItemAdapter(List<MultiItemEntity> data) { super(data);addItemType(TYPE_LEVEL_0, R.layout.item_expandable_lv0); addItemType(TYPE_LEVEL_1, R.layout.item_expandable_lv1); addItemType(TYPE_PERSON, R.layout.item_text_view);}@Overrideprotected void convert(final BaseViewHolder holder, final MultiItemEntity item) {switch (holder.getItemViewType()) {case TYPE_LEVEL_0:....//set view contentholder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int pos = holder.getAdapterPosition();if (lv0.isExpanded()) { collapse(pos);} else {expand(pos);}}});break;case TYPE_LEVEL_1:// similar with level 0break;case TYPE_PERSON://just set the contentbreak;}
}
开启所有菜单:
adapter.expandAll();
删除某一个item(添加和修改的思路是一样的)
// 获取当前父级位置int cp = getParentPosition(person);
// 通过父级位置找到当前list,删除指定下级((Level1Item)getData().get(cp)).removeSubItem(person);
// 列表层删除相关位置的数据getData().remove(holder.getLayoutPosition());
// 更新视图notifyDataSetChanged();
自定义ViewHolder
需要继承BaseViewHolder
public class MovieViewHolder extends BaseViewHolder
然后修改adapter的第二个泛型为自定义的ViewHolder
public class DataBindingUseAdapter extends BaseQuickAdapter<Movie, DataBindingUseAdapter.MovieViewHolder>
注意:需要单独建一个外部类继承BaseViewHolder,否则部分机型会出现ClassCastException,如果是内部类的构造方法要是public,定义的那个类也最好是public。
混淆
-keep class com.chad.library.adapter.** {
*;
}
-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
-keepclassmembers class **$** extends com.chad.library.adapter.base.BaseViewHolder {<init>(...);
}
扩展框架
由于adapter本身能力有限,我们又不想耦合view层所以有些需求是现实不了,于是合作了一些优秀开源库,为开发者提供更多可能性。以下扩展框架都是有结合BRVAH的demo。
- PinnedSectionItemDecoration:一个强大的粘性标签库
- EasyRefreshLayout:这个库让你轻松实现下拉刷新和上拉更多
- EasySwipeMenuLayout:独立的侧滑删除
本文章由于持续更新,建议点赞收藏,便于查看。
官方网站:www.recyclerview.org
Demo下载地址:http://fir.im/s91g
如果有问题:提问,请先看这个!
BaseQuickAdapter之BRVAH官方使用指南(持续更新)相关推荐
- unraid个人服务器使用指南——持续更新中
unraid个人服务器使用指南--持续更新中 公网访问 内网穿透 公网IP访问 unRaid系统 开心版系统下载 增加硬盘 增加与替换硬盘注意事项 群晖虚拟机安装 docker安装 清理docker ...
- BRVAH官方使用指南(持续更新)--BaseRecyclerViewAdapterHelper
项目地址:GithuGitHub BaseRecyclerViewAdapterHelper 官方网站:www.recyclerview.org BRVAH是一个强大的RecyclerAdapter框 ...
- 固件 android3.0,华为Ascend P7 EMUI3.0 官方固件-资源-持续更新(2.2更新)
本帖最后由 琼霄舞风云 于 2015-2-5 10:28 编辑 华为Ascend P7 EMUI3.0 官方固件 为了方便大家下载最新固件,小编特此整理本帖(本贴持续更新) 刷机方法参考该贴: 文件校 ...
- Python3入门指南(持续更新)
一.环境介绍 编程IDE: VS Code 运行环境: windows .Ubuntu Python版本: 3.8.0 完整PDF下载地址(持续更新资源包): https://download. ...
- 广东户外徒步指南 持续更新
最近一年时间都在户外徒步 爬了很多山 今天罗列一些,感兴趣的留言区评论即可 如果想去 也可以找我咨询线路. 户外徒步真的可以看到不一样的风景,对身体是一种锻炼,本文所有图片拍摄于iphone11,后面 ...
- 安卓知识体系搭建(持续更新)
Java基础 日期操作类 [Android]DecimalFormat简单使用 Java语言编程规范--注释规范 Java内存分配之堆.栈和常量池 Java泛型详解 深入浅出Java中的增强 for ...
- brvah树状结构默认展开第一个_BRVAH官方使用指南(持续更新)
BRVAH是一个强大的RecyclerAdapter框架(什么是RecyclerView?),它能节约开发者大量的开发时间,集成了大部分列表常用需求解决方案.为什么会有它?请查看「Android开源框 ...
- basequickadapter详解_BaseRecyclerViewAdapter(持续更新!)
>RecyclerView作为Android最常用的控件,受益群体几乎是所有Android开发者,希望更多开发者能够一起来维护这个项目,把这个项目做得更好,帮助更多人.**Star我的项目可加Q ...
- Redis-6.2.x版本官方发行说明(附谷歌翻译)【持续更新】
一.前言 本文只是单纯地翻译Redis官方的6.2.x版本的发行说明,不会对发行说明内容做任何改动,读者如果觉得有异议,可自行去Redis官方相关网页查阅.翻译工具翻译出来的不一定百分百准确,英语 ...
最新文章
- ALL ABOUT CIRCUITS 的资源整理
- chcon命令 selinux 配置等
- 哦?你会视频剪辑?是的。好,录用你!
- 无法上网之NOD32
- .ajax 上传图片,ajax图片上传并预览
- 上班两年干了些啥?该思考人生
- PCI E 阻抗85/100
- 人物-胡玮炜:胡玮炜
- 基于NT98530的多目VR摄像机方案,多sensor同步,多sensor防抖,PTP校时,实景SLAM数字孪生的最佳搭档。
- Tensorflow2.6实现Unet结构神经网络(3D卷积)识别脑部肿瘤并实现模型并行
- 安卓10侧边返回_向返回键说拜拜,安卓10向全面屏手势继续迈进
- 2032: [蓝桥杯2022初赛] 顺子日期
- SOM自组织(竞争型)神经网络(Python实现)
- 论文翻译[Deep Residual Learning for Image Recognition]
- Excel比较两个单元格内容是否相等
- PostgreSQL TID及tuple slot
- 【日语】标准日本语动词大全
- win7开机突然变得很慢_win7突然开机变慢怎么办?
- 基于JSP的猎头公司管理软件的设计
- 污染源在线监控数采仪