界面编码设计实现中,我们肯定会用到列表展示控件,大家肯定用过ListView。后来google推出了RecycleView,帮我们去做了很多优化(内置viewholder增加复用率、可以支持局部刷新、布局可以通过外层指定layout等),正常的使用,如下:

      MyRecycleViewAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_decorator);Component component = new ConCreateComponent();ComponentImplA impl1 = new ComponentImplA(component);impl1.operation();List<String> list = new ArrayList<>();for (int i = 0; i < 100; i++) {list.add("position " + i);}adapter = new MyRecycleViewAdapter(this);adapter.setData(list);}/*** 原始的yRecycleViewAdapter v1*/public void buttonv1(View view) {findViewById(R.id.recycleview).setVisibility(View.VISIBLE);findViewById(R.id.wrapperR).setVisibility(View.GONE);RecyclerView recyclerView = findViewById(R.id.recycleview);recyclerView.setLayoutManager(new LinearLayoutManager(this));recyclerView.setAdapter(adapter);}

但是RecycleView大家发现有一个问题,我们如果想要为这个RecycleView添加自定义的头部view、尾部view的话,官方这个明显做不到,那这时我们可以考虑用装饰者模式或者继承去扩展一下。

设计UML图

首先我们通过UML图,来设计一下,设计之前想一下,我们是想要扩展RecyclerView.Adapter和RecyclerView,从而可以实现addHeadView、addFootView的功能,那么需要以下几步骤。

1)首先,由于RecyclerView.Adapter已经是一个抽象类接口,我们自己继承与它,然后进行包装定义为WrapperRecyclerAdapter类
2)WrapperRecyclerAdapter肯定要持有RecyclerView.Adapter的引用,所以需要有一个构造方法,将RecyclerView.Adapter的引用传递进来
3)由于WrapperRecyclerAdapter继承与RecyclerView.Adapter,肯定要去实现关键的方法,onCreateViewHolder(创建viewitem的holder)、onBindViewHolder(viewholder数据绑定)、getItemCount(获取列表item的数量)
4)关键的一步来了,就是使用RecyclerView.Adapter、footviews、headviews,这三者组合,重写上面的三个重要方法,给列表相应位置创建对应的item

代码实现1

WrapperRecyclerAdapter

package com.itbird.design.decorator.recycleview;import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import java.util.ArrayList;
import java.util.List;/*** RecyclerView.Adapter包装类,扩展实现headView、footView的添加* Created by itbird on 2022/6/10*/
public class WrapperRecyclerAdapter extends RecyclerView.Adapter {RecyclerView.Adapter adapter;List<View> headViews = new ArrayList<>();List<View> footViews = new ArrayList<>();public WrapperRecyclerAdapter(RecyclerView.Adapter adapter) {this.adapter = adapter;adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {@Overridepublic void onChanged() {notifyDataSetChanged();}});}@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {//头部的,返回头部的viewholderif (position < headViews.size()) {return new WrapperViewHolder(headViews.get(position));}//adapter返回中间数据holderif (position >= headViews.size() && position < headViews.size() + adapter.getItemCount()) {return adapter.onCreateViewHolder(parent, adapter.getItemViewType(position - headViews.size()));}//尾部的,返回尾部的viewholderreturn new WrapperViewHolder(footViews.get(position - headViews.size() - adapter.getItemCount()));}@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {if (position < headViews.size() || position >= adapter.getItemCount() + headViews.size()) {return;}//头部和底部不需要做处理,只需要真实的adapter需要处理adapter.onBindViewHolder(holder, position - headViews.size());}@Overridepublic int getItemViewType(int position) {return position;}@Overridepublic int getItemCount() {return headViews.size() + footViews.size() + adapter.getItemCount();}public void addHeadView(View view) {if (!headViews.contains(view)) {headViews.add(view);notifyDataSetChanged();}}public void addFootView(View view) {if (!footViews.contains(view)) {footViews.add(view);notifyDataSetChanged();}}public void removeHeadView(View view) {if (headViews.contains(view)) {headViews.add(view);notifyDataSetChanged();}}public void removeFootView(View view) {if (footViews.contains(view)) {footViews.remove(view);notifyDataSetChanged();}}static class WrapperViewHolder extends RecyclerView.ViewHolder {public WrapperViewHolder(@NonNull View itemView) {super(itemView);}}
}

这时再去调用,发现就可以如下调用

    /*** 扩展的,可以增加头尾的recycleview v2*/public void buttonv2(View view) {findViewById(R.id.recycleview).setVisibility(View.VISIBLE);findViewById(R.id.wrapperR).setVisibility(View.GONE);RecyclerView recyclerView = findViewById(R.id.recycleview);recyclerView.setLayoutManager(new LinearLayoutManager(this));WrapperRecyclerAdapter wrapperRecyclerAdapter = new WrapperRecyclerAdapter(adapter);//这里head为什么不会全屏,因为LayoutInflater需要parent才会全屏wrapperRecyclerAdapter.addHeadView(LayoutInflater.from(this).inflate(R.layout.layout_header_view, recyclerView, false));wrapperRecyclerAdapter.addFootView(new Button(this));recyclerView.setAdapter(wrapperRecyclerAdapter);
//        面向对象的六大基本原则,好像不符合最小知道原则,每次调用需要去new WrapperRecyclerAdapter这样的一个包装者,这肯定是不对的,所以需要封装自己的recycleview}

看一下运行效果

代码实现2

这里我们发现一个问题,这样岂不是让开发者,每每次去使用的时候,new原始的adapter,还需要去new WrapperRecyclerAdapter,然后才能给recyclerView去setAdapter,面向对象的六大基本原则,好像不符合最小知道原则,每次调用需要去new WrapperRecyclerAdapter这样的一个包装者,这肯定是不对的,所以需要封装自己的recycleview。

所以我们做如下优化,将WrapperRecyclerAdapter的new操作,我们可以放入recyclerView中,这样外界开发者只需要去关心WrapperRecycleView和RecyclerView.Adapter就可以了,对于开发者来讲,只需关心RecyclerView自定义就可以了。

自定义WrapperRecycleView,重写方法setAdapter,用于封装new WrapperRecyclerAdapter的操作

package com.itbird.design.decorator.recycleview;import android.content.Context;
import android.util.AttributeSet;
import android.view.View;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;/*** 自定义WrapperRecycleView,重写方法setAdapter,用于封装new WrapperRecyclerAdapter的操作* Created by itbird on 2022/6/10*/
public class WrapperRecycleView extends RecyclerView {WrapperRecyclerAdapter wrapperRecyclerAdapter;public WrapperRecycleView(@NonNull Context context) {super(context);}public WrapperRecycleView(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public WrapperRecycleView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overridepublic void setAdapter(@Nullable Adapter adapter) {wrapperRecyclerAdapter = new WrapperRecyclerAdapter(adapter);super.setAdapter(wrapperRecyclerAdapter);}@Nullable@Overridepublic Adapter getAdapter() {return wrapperRecyclerAdapter;}public void addHeadView(View view) {wrapperRecyclerAdapter.addHeadView(view);}public void addFootView(View view) {wrapperRecyclerAdapter.addFootView(view);}public void removeHeadView(View view) {wrapperRecyclerAdapter.removeHeadView(view);}public void removeFootView(View view) {wrapperRecyclerAdapter.removeFootView(view);}
}

调用一下

  /*** 将wrapperadapter的new操作,内部实现 v3* 封装的必要性,这样的话,只需要关注WrapperRecycleView,不再需要关注WrapperRecyclerAdapter*/public void buttonv3(View view) {findViewById(R.id.wrapperR).setVisibility(View.VISIBLE);findViewById(R.id.recycleview).setVisibility(View.GONE);WrapperRecycleView wrapperRecycleView = findViewById(R.id.wrapperR);wrapperRecycleView.setLayoutManager(new LinearLayoutManager(this));wrapperRecycleView.setAdapter(adapter);wrapperRecycleView.addHeadView(LayoutInflater.from(this).inflate(R.layout.layout_header_view, wrapperRecycleView, false));wrapperRecycleView.addFootView(new Button(this));//这时再去考虑一个事情,我们通过装饰者模式把adapter封装了一层,如果adpater有数据更新,导致变动,这时会有问题吗?//这时会发现,并未更新,原因是装饰类,并未做事件响应}

是不是简单了很多。

可添加头尾的RecycleView的实现相关推荐

  1. 优雅的为RecyclerView添加头尾布局HeaderAndFooterWrapper

    日常的开发中,我们需要为RecyclerView添加头尾布局,当我们已经写好了一个adapter,这时候如果要现在添加头尾布局,通常的做法是重写刚写完的adapter,再getItemViewType ...

  2. 初识 android v7 包

    大家对于v4包都已经很熟悉了,现在在新建android项目时,v4包是默认导入的. v7包需要v4包的支持,在新建android项目时,v7包默认不导入,我们需要自己导入.主要对3.0以下版本提供Ac ...

  3. Leetcode-一篇帖子就够啦

    # 注:下面按照算法类别由浅入深,把下面罗列的这些题刷完,并且多看这些题不同的解法(国际版mostvotes),看懂之后估计就不会有太大的问题啦~ 整体框架 数据结构: 一维:基础: 数组array( ...

  4. 【转】使用TCP协议连续传输大量数据时,是否会丢包,应如何避免?

    [转]使用TCP协议连续传输大量数据时,是否会丢包,应如何避免? Posted on 2008-06-11 15:24 路缘 阅读(3868) 评论(0) 编辑 收藏  http://www.cnbl ...

  5. 2019-暑期实习生-自然语言处理算法岗-面试题

    随着三月初蚂蚁金服内推开启,整个暑期实习生招聘大幕也正式打开,这一场从三月初持续到之后五月的笔试面试过程,确实让笔者真真切切的感受到基础的重要性,面试和笔试不仅从机器学习,自然语言处理,数据结构与算法 ...

  6. Android view.settran,Android RecyclerView从入门到玩坏

    目录 前言 基础使用 分隔线 点击监听 搭配CardView 更丰富的条目 增删条目 快速添加视图 让RecyclerView支持复杂视图 最后前言 RecyclerView在Android界面开发当 ...

  7. Android Studio实现 历史上的今天

    文章目录 一.项目概述 二.开发环境 三.主要实现 四.项目演示 五.项目总结 六.项目源码 一.项目概述 本项目名称叫做TodayHistory,顾名思义,就是"历史上的今天". ...

  8. 【PDF】java使用Itext生成pdf文档--详解

    [API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/i ...

  9. Reporting报表开发知识汇总[个人原创]

    [个人原创] ,转发请声明原文链接 了解 a)      SSRS全称 SQL Server Reporting Services,是依赖于数据库运行的,是微软开发的重量级别的BI产品 b)      ...

最新文章

  1. 归一化互相关Normalization cross correlation (NCC)
  2. css学习任务二:切图写代码
  3. 操作系统学习:系统调用与Linux0.12初始化详细流程
  4. table的td、th的一些样式问题(宽度,边框,滚动条)
  5. Retrofit 注解参数详解
  6. 游戏设计模式思考:“穿越火线”中的“策略模式”
  7. 如何正确处理 .NET 文件的 `File in use by another process` 异常 ?
  8. vuex webpack 配置_vue+webpack切换环境和打包之后服务器配置
  9. 计算机二级c语言考试真题及答案详解,计算机二级c语言试题及答案
  10. openwrt源码分析_编译个性化的OPENWRT固件(openWRT源码修改)
  11. 用python设计简易计算器代码_Python简易计算器制作方法代码详解
  12. PS:学习:一:删除图片不想要的部分
  13. ArcMap加载SHP文件
  14. 迷你游戏平台开发(二)
  15. JZOJ 4809. 挖金矿
  16. 2021-2027全球与中国Al2O3氧化铝陶瓷基板白板市场现状及未来发展趋势
  17. 【Errors】Errors during downloading metadata for repository ‘AppStream‘:
  18. ERP与MBA的关系
  19. java判断白天黑夜,获取Java中的所有夜晚时间
  20. 小程序与公众号共用服务器端,小程序和公众号能否共用同一个数据库

热门文章

  1. 在HTML中将垂直转换为平行,大物实验答案解析.doc
  2. VL53L0X 底层思路整理 (2)
  3. 【高速数字化仪应用案例系列】虹科Spectrum在天文领域的应用
  4. oracle goldengate学习笔记,【学习笔记】Oracle goldengate monitor使用笔记
  5. Oracle显示表裂开,【案例】Oracle RAC脑裂导致节点重启原因分析
  6. 从1G说到5G:科技改变生活
  7. Fanuc开发技术集-Focas2中英文函数对照表第五部分
  8. 协作型CRM软件能帮到你什么?
  9. 《区块链工程技术人员等职业信息》
  10. java vue 服务端渲染_vue服务端渲染缓存应用详解