Universal Adapter BaseRecyclerViewAdapterHelper RecyclerView of open source framework (BRVAH) uses detailed

When the interview if you will ListView components, instead of using RecyclerView words, there may be little the company to send you offer, if you will RecyclerView use and development of general adapter, then do not understand open source framework BaseRecyclerViewAdapterHelper RecyclerView of (BRVAH) use , it is also a loss, at least the working efficiency will be much slower! Let's look at what this can do open-source framework (content translated from the official website)?

The following is a reprint content, layout slightly changed a bit, to facilitate their reading! Continue to update their code examples to put some of it!

  • Adapter optimization codes, and the adapter relative to the original, reduced by 70% of the code.
  • Add Item events
    Item click event
    Item long press event
    Item child control click event
    Item child controls of a long press event
  • Add a list loading animation: a line of code to easily switch 5 kinds of default animation.
  • Add header and footer: a line of code to get feeling back ListView era.
  • Automatic load: the load without having to listen for Raja slip event, you can customize the layout of loading, display abnormal prompt, prompt custom exception. Supports drop-down load.
  • Layout packet: the packet header defined heart.
  • Multi-layout: a simple configuration, without the need to rewrite an additional method.
  • Set an empty layout: even works better than the setEmptyView Listview.
  • Add drag, swipe to delete: open, listening to, is that simple.
  • Tree list: more powerful than ExpandableListView, multi-level support.
  • Custom ViewHolder: support custom ViewHolder, allowing developers to arbitrary.
  • Extension Framework: a combination of third-party frameworks, needs more easily customized.

So fast hardware frame looked really Brief Encounter ah, alone, automatically loads the pull-down refresh, group layout, click encapsulates a variety of events, we believe that most developers will be able to capture the hearts and minds of! (The above mentioned features, this article also catalog: https://www.jianshu.com/p/b343fcff51b0 )

The new beta version 3.x has been released for use kotlinand AndroidXwrite in support of javause. Addresses many of the remaining issues, enhanced support for DataBinding, and "multiple layout" more flexible. Of course, you can also continue to use the 2.x  version.

Framework introduced

First in build.gradle: repositories (Project XXXX) is added:

    allprojects {
        repositories {
            ...
            maven { url "https://jitpack.io" }
        }
    }

Then build.gradle (Module: app) of the dependencies added:

    dependencies {
            compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
    }

Update Description: https://github.com/CymChad/BaseRecyclerViewAdapterHelper/releases

note

版本: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).

Note: Once the case load failure occurs, only two cases:

  • Configuration is not configured
    Configuration is not configured, there are several situations:
    1. Configure up the Dependencies
    2. configuration repositories, but the location was wrong, build.gradle (Project: XXXX) repositories in the file there are two, one is buildscript below , one is allprojects below, to configure the following allprojects is right.
    3. The version number in front of a multi-v, this is my pot (of words), all versions prior to 2.1.2 with v, followed by (2.1.2 included) do not need to bring v.
  • The reason the network (this is not explained)

BaseRecyclerViewAdapterHelper adapter to use:

First need to inherit BaseQuickAdapter, and then add the generic parameter BaseQuickAdapter<Status, BaseViewHolder>of a generic Statusdata entity type, the second BaseViewHolderis ViewHolder, its purpose is to support the expansion ViewHolder.

Assignment

You can use direct viewHoldertarget point. "" Correlation methods by passing viewId and data to support chained method calls. If the network is loaded picture or custom view can viewHolder.getView(viewId)get that control.

Common method

  • viewHolder.getLayoutPosition () Gets the current item of position

Using the code

public class HomeAdapter extends BaseQuickAdapter<HomeItem, BaseViewHolder> {
    public HomeAdapter(int layoutResId, List data) {
        super(layoutResId, data);
    }

    @Override
    protected 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));
    }
}

Note: If you want to understand the principles can view RecyclerView.Adapter optimized yet?

common problem

The problem is not the use of the library, but often asked these questions, so he wrote it to help developers follow-up encounter the following problems.

Why not show the data?
Please check your RecyclerView whether a LayoutManager.

Why are there 10 data show only one?
Please check the item layout outermost Layout is not layout_heightset match_parent.

Data status confusion
this issue or whether it is RecyclerView ListView will not deal with the problem, this is essentially due to the layout of the mechanisms leading to reuse, the solution is to control the state of the state control over the data, be sure to set the state no matter what state, ifand elseis ultimately, the following code:

  if(entity.isCheck){
    checkBox.isChecked(true);
  } else {
    checkBox.isChecked(false);
  }

Cache problem solving cases:

Add Item event

Item click event

adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d(TAG, "onItemClick: ");
                Toast.makeText(ItemClickActivity.this, "onItemClick" + position, Toast.LENGTH_SHORT).show();
            }
        });

Item long press event

adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d(TAG, "onItemLongClick: ");
                Toast.makeText(ItemClickActivity.this, "onItemLongClick" + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        });

Note: Nested recycleView case you need to use adapter setOnItemClickListener to set the click event, if recycleView.addOnItemTouchListener will add a total of.

Click event Item child controls (two steps)
① first on the inside of the adapter convert method by viewHolder.addOnClickListenerbinding controls id

 @Override
    protected 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);
       
    }

② then set

 adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public boolean onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d(TAG, "onItemChildClick: ");
                Toast.makeText(ItemClickActivity.this, "onItemChildClick" + position, Toast.LENGTH_SHORT).show();
                return false;
            }
        });

Long Item child control by event (two steps)
steps above using a different method.
①adapter bound method will addOnClickListenerchange addOnLongClickListener.
② set up click event method setOnItemChildClickListenerchangedsetOnItemChildLongClickListener

Note: Set the child control events, if not bound adapter, click the event could not be effective, because they can not find the control you need to set.

如果需要在点击事件中获取其他子控件可以使用方法:

getViewByPosition(RecyclerView recyclerView, int position, @IdRes int viewId) 

注意:如果有header的话需要处理一下position加上 headerlayoutcount。

添加列表加载动画

开启动画(默认为渐显效果)
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() {
                            @Override
                            public 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动画延迟执行即可。

@Override
    protected void startAnim(Animator anim, int index) {
        super.startAnim(anim, index);
        if (index < count)
        anim.setStartDelay(index * 150);
    }

添加头部、尾部

添加头部、尾部:一行代码搞定,感觉又回到ListView时代

mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());

注:如果想深入了解的原理可以查看BaseRecyclerAdapter之添加不同布局(头部尾部)

删除指定view

mQuickAdapter.removeHeaderView(getView);
mQuickAdapter.removeFooterView(getView);

删除所有

mQuickAdapter.removeAllHeaderView();
mQuickAdapter.removeAllFooterView();

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

setHeaderAndEmpty
setHeaderFooterEmpty

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

setHeaderViewAsFlow
setFooterViewAsFlow

自动加载(上拉加载、下拉刷新)

上拉加载无需监听滑动事件,可自定义加载布局,显示异常提示,自定义异常提示。

// 滑动最后一个Item的时候回调onLoadMoreRequested方法
setOnLoadMoreListener(RequestLoadMoreListener);

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

mQuickAdapter.disableLoadMoreIfNotFullPage();

回调处理代码

mQuickAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override public void onLoadMoreRequested() {
                mRecyclerView.postDelayed(new Runnable() {
                    @Override
                    public 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());

自定义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"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_40">

    <LinearLayout
        android:id="@+id/load_more_loading_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/loading_progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="?android:attr/progressBarStyleSmall"
            android:layout_marginRight="@dimen/dp_4"
            android:indeterminateDrawable="@drawable/sample_footer_loading_progress"/>

        <TextView
            android:id="@+id/loading_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dp_4"
            android:text="@string/loading"
            android:textColor="#0dddb8"
            android:textSize="@dimen/sp_14"/>
    </LinearLayout>

    <FrameLayout
        android:id="@+id/load_more_load_fail_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">


        <TextView
            android:id="@+id/tv_prompt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textColor="#0dddb8"
            android:text="@string/load_failed"/>

    </FrameLayout>

</FrameLayout>

下拉加载(符合聊天软件下拉历史数据需求)

设置开启开关

 mAdapter.setUpFetchEnable(true);

设置监听

mAdapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {
            @Override
            public 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() {
            @Override
            public void run() {
                mAdapter.addData(0, getData());
                /**
                 * 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> {
    //构造方法需要传入两个布局id,第一个是item的,第二个是head的
    public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {
        super(layoutResId, sectionHeadResId, data);
    }

    //在convert方法里面加载item数据
    @Override
    protected void convert(BaseViewHolder helper, MySection item) {
        helper.setImageUrl(R.id.iv, (String) item.t);
    }

    //在convertHead方法里面加载head数据
    @Override
    protected void convertHead(BaseViewHolder helper,final MySection item) {
        helper.setText(R.id.header, item.header);
       
        helper.setOnClickListener(R.id.more, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show();
            }
        });
    }

多布局

实体类必须实现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;
    }

    @Override
    public int getItemType() {
        return itemType;
    }
}

在构造里面addItemType绑定type和layout的关系

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleItem, BaseViewHolder> {
    //在构造里面addItemType绑定type和layout的关系
    public MultipleItemQuickAdapter(List data) {
        super(data);
        addItemType(MultipleItem.TEXT, R.layout.text_view);
        addItemType(MultipleItem.IMG, R.layout.image_view);
    }

    @Override
    protected 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() {
            @Override
            public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
                return data.get(position).getSpanSize();
            }
        });

如果大家觉得这种多布局方式有点由于耦合了实体类,还有支持另外一种多布局方式具体可查看更便捷的多布局, 为 BaseQuickAdapter 设置代理.

 

更便捷的多布局, 为 BaseQuickAdapter 设置代理

 public class MultiDelegateAdapter extends BaseQuickAdapter<Entity, BaseViewHolder> {

        public MultiDelegateAdapter() {
            super(null);
            //Step.1
            setMultiTypeDelegate(new MultiTypeDelegate<Entity>() {
                @Override
                protected int getItemType(Entity entity) {
                    //根据你的实体类来判断布局类型
                    return entity.type;
                }
            });
            //Step.2
            getMultiTypeDelegate()
                    .registerItemType(Entity.TEXT, R.layout.item_text_view)
                    .registerItemType(Entity.IMG, R.layout.item_image_view);
        }

        @Override
        protected void convert(BaseViewHolder helper, Entity entity) {
            //Step.3
            switch (helper.getItemViewType()) {
                case Entity.TEXT:
                    // do something
                    break;
                case Entity.IMG:
                    // do something
                    break;
            }
        }
    }

多布局代理很简单,在任何继承与BaseQuickAdapter的 adapter 上都可以实现,分为三步,如下:

Step.1

  • setMultiTypeDelegate(), 并重写getItemType() 方法
    需要说明的是Entity 并不需要实现任何接口 ,只需要能够判断出该实体对应的是哪个布局类型即可

Step.2

  • getMultiTypeDelegate().registerItemType() 设置每种type对应的布局

Step.3

  • 分 type 进行 convert() 操作

OK, 多布局就可以顺利的运行了

如果使用多布局出现这个NotFoundException异常,有可能是addItemType()两个参数写反了

// 没有数据的时候默认显示该布局
mQuickAdapter.setEmptyView(getView());

如果用网格布局的话,设置空布局就不能给全屏,可以使用瀑布流布局。

添加拖拽、滑动删除

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

OnItemDragListener onItemDragListener = new OnItemDragListener() {
    @Override
    public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){}
    @Override
    public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {}
    @Override
    public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {}
}

OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
    @Override
    public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public 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);
    }

    @Override
    protected 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);
    }
    @Override
    protected void convert(final BaseViewHolder holder, final MultiItemEntity item) {
        switch (holder.getItemViewType()) {
        case TYPE_LEVEL_0:
            ....
            //set view content
           holder.itemView.setOnClickListener(new View.OnClickListener() {
               @Override
               public void onClick(View v) {
                   int pos = holder.getAdapterPosition();
                   if (lv0.isExpanded()) { 
                       collapse(pos);
                   } else {
                       expand(pos);
                   }
           }});
           break;
        case TYPE_LEVEL_1:
           // similar with level 0
           break;
        case TYPE_PERSON:
           //just set the content
           break;
    }
}

开启所有菜单:

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。

本文章由于持续更新,建议点赞收藏,便于查看。

官方网站:www.recyclerview.org
Demo下载地址:http://fir.im/s91g

如果有问题:提问,请先看这个!

两个很不错的地址:

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

    简书:https://www.jianshu.com/p/b343fcff51b0

 

 

发布了9 篇原创文章 · 获赞 0 · 访问量 1418

Guess you like

Origin blog.csdn.net/luqingshuai_eloong/article/details/104369674