代码放在:
效果
image.png
实现逻辑 (一共3个kt文件)
Adapter.kt
/**
* 通用 RecyclerView.Adapter类, 基本结构与普通RecyclerView.Adapter一致.
* 内部使用一个arrayList列表变量dataItems来存储数据, 提供了addData和replace两个方法来更新数据
* 在onCreateViewHolder中会根据viewType找到对应的viewHolder类,并创建iewHolder类实例, 如果找不到则返回一个空实现EmptyVH实例
* 在onBindViewHolder中,交给VH实例自己进行数据绑定操作
*/
class Adapter(val context: Context) : RecyclerView.Adapter<VH<Data>>() {
private val dataItems = ArrayList<Data>()
override fun getItemViewType(position: Int): Int {
return dataItems[position].itemViewType
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH<Data> {
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
VHList[viewType]?.let {
return it(view) as VH<Data>
}
return EmptyVH(view)
}
override fun onBindViewHolder(holder: VH<Data>, position: Int) {
holder.bind(dataItems[position], position)
}
override fun getItemCount(): Int {
return dataItems.size
}
fun addData(list: List<Data>) {
dataItems.addAll(list)
notifyDataSetChanged()
}
fun replace(list: List<Data>) {
dataItems.run {
clear()
addAll(list)
}
notifyDataSetChanged()
}
}
Data.kt
interface Data {
val itemViewType: Int
}
open class CommonData(
override var itemViewType: Int,
vHConstructorFuc: (view: View)-> VH<out Data>)
: Data {
init {
VHList.register(itemViewType, vHConstructorFuc)
}
}
VH.kt
/**
* 自定义的RecyclerView.ViewHolder子类.主要是为了增加bind(data: Data, position: Int)方法
*/
abstract class VH<T : Data>(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(data: T, position: Int)
}
/**
* ViewHolder的注册表, 建立itemViewType与ViewHolder的对应关系
* 存放在map中, 效率凑合
*/
object VHList {
private var vhs = mutableMapOf<Int, (view: View) -> VH<out Data>>()
fun register(viewType: Int, vHConstructorFuc: (view: View) -> VH<out Data>) {
vhs[viewType] = vHConstructorFuc
}
operator fun get(viewType: Int): ((view: View) -> VH<out Data>)? = vhs[viewType]
}
/**
* 这是一个空ViewHolder实现, 只会抛出异常
*/
class EmptyVH(itemView: View) : VH<Data>(itemView) {
override fun bind(data: Data, position: Int) {
TODO("not implemented")
}
}
使用示例:
NotSimpleListActivity.kt:
class NotSimpleListActivity : AppCompatActivity() {
private lateinit var adapter: Adapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_simple_list)
recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
adapter = Adapter(this)
recyclerview.adapter = adapter
loadOnlineData()
}
private fun loadOnlineData() {
ApiService.get()!!
.getHotScreenList(mapOf("apikey" to API_KEY, "count" to "30"))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onError ={ Log.e("NotSimpleListActivity", "error", it) },
onNext = {
adapter.addData(it!!.subjects?.map {
HotScreenData(it, R.layout.douban_hotscreen_item_layout,::HotScreenDataViewHolder)
}!!)
}
)
}
}
/**
* define the wrapper data
*/
class HotScreenData(var backdata: HotScreenResult.SubjectsBean,
layoutId: Int,
funct: (view: View) -> VH<out Data>)
: CommonData(layoutId, funct)
class HotScreenDataViewHolder : VH<HotScreenData> {
var title: TextView? = null
var dy: TextView? = null
var actor: TextView? = null
var watchNum: TextView? = null
var rating: RatingBar? = null
var image: ImageView? = null
constructor(itemView: View) : super(itemView) {
itemView.apply {
title = findViewById(R.id.item_hot_screen_title)
image = findViewById(R.id.item_hot_screen_image)
rating = findViewById(R.id.item_hot_screen_rating)
dy = findViewById(R.id.item_hot_screen_dy)
actor = findViewById(R.id.item_hot_screen_actor)
watchNum = findViewById(R.id.item_hot_screen_watch_num)
}
}
override fun bind(data: HotScreenData, position: Int) {
title?.text = data.backdata.title
Glide.with(itemView.context).load(data.backdata.images?.small).into(image!!)
rating?.rating = (data.backdata.rating?.average!! / 2).toFloat()
dy?.text = "导演:" + data.backdata.directors!![0].name
watchNum?.text = "${data.backdata.collect_count} 人看过"
actor?.text = "主演:" + data.backdata.casts!!.map { it.name }
}
}
这段代码就实现了本篇头部的效果截图.
总结
这个框架(实在想不出该用什么词表示了)最大的好处是数据与现实元素的聚合, 对于页面显示复杂的应用, 可以方便的添加recyclerview中的显示类型(viewType), 避免了大量if/when判断分支.
实现简单, 只有3个kt文件.
代码无侵入性, 非常接近原生的使用方式;
所有的viewHolder都与数据相对应, 高聚合, 且代码更清爽.
网友评论