Brvah在RecyclerView中的使用

BRVAH在RecyclerView中的使用


前言

RecyclerView虽然好用但是确实比起ListView使用难度上略大,写过五遍以上的原始的RecyclerView.Adapter后我迫切的打开了全球最大单生交友平台GitHub,寻找BaseAdapter for RecyclerView。然后我找到了BAVAH。哈哈赶快学习一下。
BRVAH github地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper

学习目标

  • 加载普通列表布局
  • item点击事件,item子元素点击事件
  • item设置加载动画
  • 下拉刷新上拉加载
  • RecyclerView添加头部和尾部
  • 多类型item列表
  • 恩 暂时就先这么多吧,后续有新需求再持续更新......

具体实现

先看看效果,实现凤凰新闻客户端新闻列表,包含banner头部和三张item类型的新闻列表,实现底部自动加载更多,下拉刷新。点击item能够进入新闻详情页面

image.png
M2YRF_4R__5%AY3RUJ5)YOI.png

image.png

先来看看实现这么一个复杂的列表所使用的adapter代码量有多少:

public class DocNewsAdapter extends BaseMultiItemQuickAdapter<BRVAHActivity.NewsBean, BaseViewHolder> {
    private Context context;
    private List<BRVAHActivity.NewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<BRVAHActivity.NewsBean> list) {
        super(list);
        this.context = context;
        this.list = list;
        addItemType(BRVAHActivity.NewsBean.doc, R.layout.item_doc_news);
        addItemType(BRVAHActivity.NewsBean.slide, R.layout.item_slide_news);
        addItemType(BRVAHActivity.NewsBean.text_live, R.layout.item_textlive_news);
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, BRVAHActivity.NewsBean item) {

        switch (baseViewHolder.getItemViewType()) {

            case BRVAHActivity.NewsBean.doc:
                baseViewHolder.setText(R.id.txt_doc_title, item.docNewsBean.getTitle())
                        .setText(R.id.txt_doc_commentsall, item.docNewsBean.getCommentsall())
                        .setText(R.id.txt_doc_source, item.docNewsBean.getSource())
                        .setText(R.id.txt_doc_updateTime, item.docNewsBean.getUpdateTime());
                Glide.with(context).load(item.docNewsBean.getThumbnail()).placeholder(R.drawable.ic_fh_defals)
                        .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_doc_thumbnail));
                baseViewHolder.addOnClickListener(R.id.img_doc_thumbnail);
                break;
            case BRVAHActivity.NewsBean.slide:
                baseViewHolder.setText(R.id.txt_slide_title, item.slideNewsBean.getTitle())
                        .setText(R.id.txt_slide_commensall, item.slideNewsBean.getCommentsall())
                        .setText(R.id.txt_slide_resource, item.slideNewsBean.getSource());
                for (int i = 0; i < item.slideNewsBean.getStyle().getImages().size(); i++) {
                    if (i == 0)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img1));
                    else if (i == 1)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img2));
                    else if (i == 2)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img3));
                }
                break;
            case BRVAHActivity.NewsBean.text_live:
                baseViewHolder.setText(R.id.txt_textlive_title, item.textLiveNewsBean.getTitle());
                Glide.with(context).load(item.textLiveNewsBean.getThumbnail()).placeholder(R.drawable.ic_fh_defals)
                        .centerCrop().into((ImageView) baseViewHolder.getView(R.id.img_textlive_thumbnail));
                break;
        }
    }
}

完成全部功能的activity代码


public class BRVAHActivity extends AppCompatActivity implements BaseQuickAdapter.OnItemClickListener,
        BaseQuickAdapter.OnItemChildClickListener, BaseQuickAdapter.RequestLoadMoreListener, SwipeRefreshLayout.OnRefreshListener {
    Toolbar toolbar;
    LinearLayout container;
    int currentPage = 0, totalPage = 0;
    boolean isRefresh = true;//当前操作是否是下拉刷新
    List<NewsBean> list = new ArrayList<>();
    @BindView(R.id.recyc_news)
    RecyclerView recyclerView;
    DocNewsAdapter adapter;
    @BindView(R.id.swipeRefreshLayout)
    SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_brvah);
        ButterKnife.bind(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }
        toolbar = (Toolbar) findViewById(R.id.tb_toolbar);
        setSupportActionBar(toolbar);
        requestData(currentPage);
        adapter = new DocNewsAdapter(BRVAHActivity.this, list);
        recyclerView.setLayoutManager(new LinearLayoutManager(BRVAHActivity.this));
        recyclerView.setAdapter(adapter);
        //item点击事件
        adapter.setOnItemClickListener(this);
        //item子元素点击事件
        adapter.setOnItemChildClickListener(this);
//        adapter.openLoadAnimation();
        adapter.isFirstOnly(false);
        //adapter设置头部banner
        adapter.addHeaderView(initBanner());
        //自动加载
        adapter.setOnLoadMoreListener(this);
        //上拉刷新
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.rgb(47, 223, 189));
    }

    /**
     * 初始化banner
     */
    private View initBanner() {
        container = (LinearLayout) findViewById(R.id.container);
        View customBanner = LayoutInflater.from(this).inflate(R.layout.custom_banner, container, false);
        ViewGroup viewGroup = (ViewGroup) customBanner;
        Banner banner = (Banner) viewGroup.getChildAt(0);
        banner.setOnBannerListener(new OnBannerListener() {
            @Override
            public void OnBannerClick(int position) {
                Toast.makeText(BRVAHActivity.this, "点击了focus news" + position, Toast.LENGTH_SHORT).show();
            }
        });
        return customBanner;
    }

    /**
     * 请求新闻数据
     *
     * @param page 第几页新闻
     */
    private void requestData(final int page) {
        OkHttpUtils
                .get()
                .url(API.getFh_toutiao() + page)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        Toast.makeText(BRVAHActivity.this, "网络请求失败,请检查网络设置", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        JSONObject data = (JSONObject) JSON.parseArray(response).get(0);
                        totalPage = data.getInteger("totalPage");
                        currentPage = data.getInteger("currentPage");
                        JSONArray item = data.getJSONArray("item");
                        for (int i = 0; i < item.size(); i++) {
                            JSONObject newsData = (JSONObject) item.get(i);
                            String newsType = newsData.getString("type");
                            if (newsType.equals("doc")) {
                                DocNewsBean docNewsBean = JSON.parseObject(item.get(i).toString(), DocNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.doc, docNewsBean, null, null);
                                list.add(newsBean);
                            } else if (newsType.equals("slide")) {
                                SlideNewsBean slideNewsBean = JSON.parseObject(item.get(i).toString(), SlideNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.slide, null, slideNewsBean, null);
                                list.add(newsBean);
                            } else if (newsType.equals("text_live")) {
                                TextLiveNewsBean textLiveNewsBean = JSON.parseObject(item.get(i).toString(), TextLiveNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.text_live, null, null, textLiveNewsBean);
                                list.add(newsBean);
                            }
                        }
                        adapter.notifyDataSetChanged();
                        if (isRefresh) {
                            //结束下拉刷新动画
                            mSwipeRefreshLayout.setRefreshing(false);
                        } else {
                            //结束加载更多动画
                            adapter.loadMoreComplete();
                        }

                    }
                });
    }

    /**
     * item的点击事件
     *
     * @param adapter  设置点击事件的Adapter
     * @param view     item的view
     * @param position item位置
     */
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        Intent intent = new Intent(BRVAHActivity.this, NewsDitailsActivity.class);
        String url = null;
        if (list.get(position).docNewsBean != null)
            url = list.get(position).docNewsBean.getLink().getWeburl();
        else if (list.get(position).slideNewsBean != null)
            url = list.get(position).slideNewsBean.getLink().getWeburl();
        else if (list.get(position).textLiveNewsBean != null)
            url = list.get(position).textLiveNewsBean.getLink().getWeburl();
        intent.putExtra("url", url);
        startActivity(intent);
    }

    /**
     * item子元素点击事件
     *
     * @param adapter
     * @param view
     * @param position
     * @return
     */
    @Override
    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击子元素中的图片" + position, Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onLoadMoreRequested() {
        isRefresh = false;
        if (currentPage < totalPage) {
            requestData(currentPage + 1);
        } else {
            adapter.loadMoreEnd();
        }

    }

    /**
     * 下拉刷新
     */
    @Override
    public void onRefresh() {
        isRefresh = true;
        currentPage = 0;
        list.clear();
        requestData(currentPage);
    }

    /**
     * 包含三种类型的新闻实体
     */
    public class NewsBean implements MultiItemEntity {
        public DocNewsBean docNewsBean;
        public SlideNewsBean slideNewsBean;
        public TextLiveNewsBean textLiveNewsBean;
        private int itemType;
        public static final int doc = 1;
        public static final int slide = 2;
        public static final int text_live = 3;

        public NewsBean(int itemType, DocNewsBean docNewsBean, SlideNewsBean slideNewsBean, TextLiveNewsBean
                textLiveNewsBean) {
            this.docNewsBean = docNewsBean;
            this.slideNewsBean = slideNewsBean;
            this.textLiveNewsBean = textLiveNewsBean;
            this.itemType = itemType;
        }

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

减少了绝大部分adapter代码量,效率还是非常高的。

仿照凤凰新闻客户端头条新闻列表部分,使用RecyclerView+BRVAH实现具有banner头部的新闻列表,具有上拉刷新下拉加载,点击查看新闻详情的功能。凤凰新闻-头条新闻列表如下:
项目使用到的库如下:



dependencies {
    ...
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'cn.yipianfengye.android:zxing-library:1.1'
    compile 'com.jakewharton:butterknife:8.8.1'
     annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    compile 'com.zhy:okhttputils:2.6.2'
    compile 'net.qiujuer.genius:ui:2.0.0'
    compile 'net.qiujuer.genius:res:2.0.0'
    compile 'de.hdodenhof:circleimageview:2.1.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    testCompile 'junit:junit:4.12'
    compile files('libs/fastjson-1.2.36.jar')
    compile files('libs/glide-3.7.0.jar')
    compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
}


1: 加载普通列表布局

现加载凤凰新闻type为doc的普通新闻数据列表


初始化Adapter,三部曲没啥好说的

adapter = new DocNewsAdapter(BRVAHActivity.this, list);
recyclerView.setLayoutManager(new LinearLayoutManager(BRVAHActivity.this));
recyclerView.setAdapter(adapter);

Adapter实现如下,传入数据绑定即可(R.layout.item_doc_news是item布局,list是新闻数据实体类)

 public class DocNewsAdapter extends BaseQuickAdapter<DocNewsBean, BaseViewHolder> {
    private Context context;
    private List<DocNewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<DocNewsBean> list) {
        super(R.layout.item_doc_news,list);
        this.context = context;
        this.list = list;
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, DocNewsBean item) {
        baseViewHolder.setText(R.id.txt_doc_title, item.getTitle())
                .setText(R.id.txt_doc_commentsall, item.getCommentsall())
                .setText(R.id.txt_doc_source, item.getSource())
                .setText(R.id.txt_doc_updateTime, item.getUpdateTime());
        Glide.with(context).load(item.getThumbnail()).placeholder(R.drawable.ic_fh_defals).crossFade().into((ImageView) baseViewHolder.getView(R.id.img_doc_thumbnail));
    }
}   

效果如如下:

123.png

2:item,item子元素点击事件

activity中调用

        //item点击事件
        adapter.setOnItemClickListener(this);
        //item子元素点击事件
        adapter.setOnItemChildClickListener(this);

/**
     * item的点击事件
     *
     * @param adapter  设置点击事件的Adapter
     * @param view     item的view
     * @param position item位置
     */
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击了第" + position + "个item", Toast.LENGTH_SHORT)
                .show();
    }

    /**
     * item子元素点击事件
     *
     * @param adapter
     * @param view
     * @param position
     * @return
     */
    @Override
    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击子元素中的图片" + position, Toast.LENGTH_SHORT).show();
    }

子元素的点击需要再Adapter中进行绑定

/**
 * 新闻列表adapter
 * Created by CYQ on 2017/8/26.
 */
public class DocNewsAdapter extends BaseQuickAdapter<DocNewsBean, BaseViewHolder> {
    private Context context;
    private List<DocNewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<DocNewsBean> list) {
        super(R.layout.item_doc_news, list);
        this.context = context;
        this.list = list;
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, DocNewsBean item) {
        baseViewHolder.setText(R.id.txt_doc_title, item.getTitle())
                .setText(R.id.txt_doc_commentsall, item.getCommentsall())
                .setText(R.id.txt_doc_source, item.getSource())
                .setText(R.id.txt_doc_updateTime, item.getUpdateTime());
        //为子元素中的图片设置点击事件
        Glide.with(context).load(item.getThumbnail()).placeholder(R.drawable.ic_fh_defals).crossFade().into((ImageView)
                baseViewHolder.getView(R.id.img_doc_thumbnail));
        baseViewHolder.addOnClickListener(R.id.img_doc_thumbnail);
    }
}

这么简单就实现了item和他的子元素的点击事件,比起原生的Adapter少了太多的代码了。


item设置加载动画

个人感觉为item设置动画没太大的实际用途,哈哈BRVAH为item设置动画一行代码搞定

 adapter.openLoadAnimation();

BRVAH为开发者提供了五中默认的动画效果:渐显、缩放、从下到上,从左到右、从右到左通过quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);设置即可


下拉刷新上拉加载

下拉刷新使用Android SDK自带的SwipeRefreshLayout

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyc_news"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
 //上拉刷新
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.rgb(47, 223, 189));
        //............
         /**
     * 下拉刷新
     */
    @Override
    public void onRefresh() {
        //刷新操作
    }

上拉加载

BRVAH提供了自动加载更多的属性,也可以自定义加载更多的view

//上拉自动加载
adapter.setOnLoadMoreListener(this);
...
@Override
    public void onLoadMoreRequested() {
        //加载更多操作
    }

恩就是这么方便就实现了列表上拉加载下拉刷新的功能


添加头部banner
这里我自定义了一个banner轮播View,BRVAH为RecyclerView提供了和listview一样方便的增加头部的功能addHeadView(youHeadView).

adapter.addHeaderView(initBanner());

initBanner();是我自定义的广告banner,返回一个view类型,把他替换成你要add的view就OK。

   /**
     * 初始化banner
     */
    private View initBanner() {
        container = (LinearLayout) findViewById(R.id.container);
        View customBanner = LayoutInflater.from(this).inflate(R.layout.custom_banner, container, false);
        ViewGroup viewGroup = (ViewGroup) customBanner;
        Banner banner = (Banner) viewGroup.getChildAt(0);
        banner.setOnBannerListener(new OnBannerListener() {
            @Override
            public void OnBannerClick(int position) {
                Toast.makeText(BRVAHActivity.this, "点击了focus news" + position, Toast.LENGTH_SHORT).show();
            }
        });
        return customBanner;
    }

多类型item列表

持续更新中。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,888评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,677评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,386评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,726评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,729评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,337评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,902评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,807评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,349评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,439评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,567评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,242评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,933评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,420评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,531评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,995评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,585评论 2 359

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,302评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,791评论 22 665
  • 原文链接:https://github.com/opendigg/awesome-github-android-u...
    IM魂影阅读 32,944评论 6 472
  • 深秋了,蛐蛐儿的叫声似乎染上了疲累,蜜蜂儿飞得也不那么欢快了。这个时节除了让人垂涎欲滴、留恋不已的大闸蟹,...
    昵称燕子阅读 161评论 0 0
  • 吴家有女百家求,粉面玉肌比清流。 飞来燕子恐纤细,池上芙蕖慕情柔。 才子词人皆倾倒,锦帛金锭日不休。 佳期默默无人...
    圆以为阅读 261评论 0 0