前言
一个高复用、低耦合的代码不会让你在第一次去实现代码的时候感到舒服
但是他会在你后面做扩展、和同类需求的时候,直呼真香!!!
最近写需求,借用到装饰者思想做了RecyclerView的头和尾的扩展
感觉很不错,赶紧拿出来说一说,嘻嘻
ps:本篇文章只是帮助大家,在实现需求的过程中也能潜移默化的使用设计模式来优化代码
Android中的装饰者
首先一句话总结装饰者:就是不通过继承的方式,来扩展某个对象的功能,达到我们想要实现的效果。
举两个小例子,不细说,因为前面已经讲过装饰者模式相关的内容
- InputStream装饰者
InputStream装饰者:在Android中,我们经常需要读取文件或者网络流。InputStream是用于读取字节流的抽象类,而Android提供了许多装饰者类来扩展InputStream的功能。
例如,BufferedInputStream和DataInputStream都是InputStream的装饰者类,它们添加了缓冲和数据类型转换的功能。
FileInputStream fileInputStream = new FileInputStream("example.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);
- View装饰者
Android中的UI组件都继承自View类,而Android提供了装饰者类来扩展View的功能
例如,可以使用LayoutInflater来给布局文件添加一些额外的装饰
LayoutInflater inflater = LayoutInflater.from(context);
View originalView = inflater.inflate(R.layout.original_layout, parentLayout, false);
ViewDecorator viewDecorator = new ViewDecorator(originalView);
View decoratedView = viewDecorator.decorate();
parentLayout.addView(decoratedView);
基于这种思想,在做RecyclerView的头和尾的扩展想到了,利用这种装饰者扩展的方式去加头和尾,而保留中间数据层的原有属性。
代码实现
利用DecorateAdapter去装饰RecyclerView.Adapter,从而扩展HeadView、FooterView
中间内容我们使用contentAdapter来表示,假设就是简单的Item结构,就不做代码介绍了。
第一步:创建装饰器DecorateAdapter
创建装饰器DecorateAdapter并实现增加头部和尾部Item的相关方法、和成员变量
并将contentAdapter作为原始的内容列表
class DecorateAdapter(
val contentAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), IdecorateList {
/**save head View*/
private val headerList: MutableList<View> by lazy {
mutableListOf()
}
/**save footer view*/
private val footerList: MutableList<View> by lazy {
mutableListOf()
}
/**常规方法*/
......
......
override fun getItemCount(): Int {
//记得加上contentAdapter的Item条目
return contentAdapter.itemCount + headerList.size + footerList.size
}
override fun addHeaderView(header: View) {
if (!headerList.contains(header)) {
headerList.add(header)
refreshList()
}
}
override fun removeHeaderView(header: View) {
if (headerList.contains(header)) {
headerList.remove(header)
refreshList()
}
}
override fun addFooterView(foot: View) {
if (!footerList.contains(foot)) {
footerList.add(foot)
refreshList()
}
}
override fun removeFooterView(foot: View) {
if (footerList.contains(foot)) {
footerList.remove(foot)
refreshList()
}
}
override fun refreshList() {
notifyDataSetChanged()
}
}
第二步:处理头部、中间内容、尾部的绑定关系
- 处理头部、中间、尾部的不同绑定的视图:也就是createHeaderViewHolder处理
/**创建头部的ViewHolder*/
private fun createHeaderViewHolder(view: View): RecyclerView.ViewHolder {
return HeaderViewHolder(view)
}
/**创建尾部的ViewHolder*/
private fun createFooterViewHolder(view: View): RecyclerView.ViewHolder {
return FooterViewHolder(view)
}
override fun onCreateViewHolder(parent: ViewGroup, position: Int): RecyclerView.ViewHolder {
/**头部样式展示*/
if (headerList.isNotEmpty() && position in 0 until headerList.size) {
return createHeaderViewHolder(headerList[position])
}
/**中间内容展示*/
val startPosition = if (headerList.isNotEmpty()) headerList.size else 0
val endPosition =
if (headerList.isNotEmpty()) headerList.size + contentAdapter.itemCount else contentAdapter.itemCount
if (position in startPosition until endPosition) {
return contentAdapter.onCreateViewHolder(parent, position)
}
/**尾部样式展示*/
return createFooterViewHolder(footerList[position - endPosition]) /**注意这里的取值*/
}
- 处理处理头部、中间、尾部的数据绑定:也就是onBindViewHolder的处理
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (headerList.isNotEmpty() && position in 0 until headerList.size) {
return
}
/**中间的内容数据绑定*/
val startPosition = if (headerList.isNotEmpty()) headerList.size else 0
val endPosition =
if (headerList.isNotEmpty()) headerList.size + contentAdapter!!.itemCount else contentAdapter!!.itemCount
if (position in startPosition until endPosition) {
/**注意计算的时候,要减去HeadView*/
contentAdapter?.onBindViewHolder(holder, position - headerList.size)
}
}
第三步:装饰器的使用
把内容区域的ContentAdapter,通过DecorateAdapter进行包装,之后调用包装后的decorateAdapter进行添加HeadView
decorate = findViewById(R.id.rv_decorate)
val decorateAdapter = DecorateAdapter(ContentAdapter())
decorate.adapter = decorateAdapter
decorate.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
decorateAdapter.addHeaderView(
LayoutInflater.from(this).inflate(R.layout.layout_header, decorate, false)
)
第四步:改进、直接封装一个View出来
把装饰者封在内部
毕竟我们在调用的时候,还是想当一个View直接拿来用,改进一下
class decorateRecyclerView : RecyclerView {
private var DecorateAdapter: DecorateAdapter? = null
@JvmOverloads
constructor(context: Context, attributes: AttributeSet? = null) : super(context, attributes)
override fun setAdapter(adapter: Adapter<ViewHolder>?) {
DecorateAdapter = DecorateAdapter(adapter!!)
super.setAdapter(DecorateAdapter)
}
fun addHeaderView(header: View) {
DecorateAdapter?.addHeaderView(header)
}
fun removeHeaderView(header: View) {
DecorateAdapter?.removeHeaderView(header)
}
fun addFooterView(foot: View) {
DecorateAdapter?.addFooterView(foot)
}
fun removeFooterView(foot: View) {
DecorateAdapter?.removeFooterView(foot)
}
}
调用 & 使用
decorate = findViewById(R.id.rv_decorate)
decorate.adapter = ContentAdapter()
decorate.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
decorate.addHeaderView(
LayoutInflater.from(this).inflate(R.layout.layout_header, decorate, false)
)
decorate.addFooterView(
LayoutInflater.from(this).inflate(R.layout.layout_footer, decorate, false)
)
总结
本篇呢,只是想说一下如何去潜移默化的使用设计模式去改变我们的代码。
举了一个扩展RecyclerView头和尾的例子。
如果不用设计模式的话,我想你的头和尾的处理逻辑都是需要冗余在ContentAdapter中的
问题:
1、那么你的ContentAdapter的定义界限是什么?整个页面的业务?那难免太难维护了
2、如果只需要服用ContentAdapter怎么处理?粘贴复制,多造一个类出来?文章来源:https://www.toymoban.com/news/detail-736029.html
而通过上面我们介绍的装饰者模式就能解决这两个:复用、耦合的问题文章来源地址https://www.toymoban.com/news/detail-736029.html
到了这里,关于设计思想培养:装饰者模式下的RecyclerView添加头、尾的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!