与 MultiType 的异同
appdev opened this issue · comments
这个和MultiType有什么区别呢?
@huclengyue
核心**是一样的【数据驱动视图】,区别在实现和使用上
1. 我们最终是要形成一种数据与视图的对应关系,即 MoreType 的 data 和 viewType。
- MultiType 在当时我看的时候,是使用 list 实现,通过相同的 index 形成一个对应关系。
- MoerType 采用 SparseArrayCompat 实现,通过在 viewType 中返回的 layout 作为 key 来确定对应关系,在 Android 中布局是唯一的,也可以说一种布局代表一种视图。
2. 更简单的实现视图
只需要继承 MoerViewType<T: Any>()
并重写三个方法,这三个方法的目的也很明确
getViewLayout()
: 返回视图的布局,当成唯一的 key 来和 data 确定关系,同时用于创建 ViewHoldergetViewModel()
: 返回视图对应的数据类(data),即声明视图所对应的数据类bindData ()
: 绑定数据,处理各种事件,内置点击事件实现方法
可以看到,我们并不用去重复写 ViewHolder,如果配合 kotlin-android-extensions
连 findViewId
也省去了,下面是实现简单的聊天界面的 viewType 代码,非常简洁,相信了解 kotlin 的语法的话不需要任何注释你也可以看得懂
class MessageInViewType : MoreViewType<Message>() {
override fun getViewLayout(): Int = R.layout.item_view_multi_message_in
override fun getViewModel(): KClass<Message> = Message::class
override fun bindData(data: Message, holder: MoreViewHolder) {
holder.itemView.message_icon.setImageURI(data.icon)
if (data.showTime) {
holder.itemView.message_time.visibility = View.VISIBLE
holder.itemView.message_time.text = Utils.sendTime(data.time.toLong() * 1000)
} else {
holder.itemView.message_time.visibility = View.INVISIBLE
}
holder.itemView.message_content_layout.removeAllViews()
var currentLayout: RelativeLayout? = null
when (data.messageType) {
"text" -> {
currentLayout = LayoutInflater.from(holder.itemView.context).inflate(R.layout.widget_view_message_in_text, holder.itemView.message_content_layout, false) as RelativeLayout
val text = currentLayout.findViewById<AppCompatTextView>(R.id.message_in_text)
text.text = data.text
}
"image" -> {
currentLayout = LayoutInflater.from(holder.itemView.context).inflate(R.layout.widget_view_message_in_image, holder.itemView.message_content_layout, false) as RelativeLayout
val image = currentLayout.findViewById<SimpleDraweeView>(R.id.message_in_image)
image.setImageURI(data.url)
setImgSize(data.width, data.height, image)
}
else -> {
}
}
holder.itemView.message_content_layout.addView(currentLayout)
}
fun setImgSize(width: String, height: String, image: SimpleDraweeView) {
val size = Utils.getIMImageSize(width.toDouble(), height.toDouble())
val lp = image.layoutParams
lp.width = size.width
lp.height = size.height
image.layoutParams = lp
}
}
3. adapter 链式使用
先看一个完整的使用例子
adapter.userSoleRegister()
.register(TitleViewType())
.register(CompleteViewType())
.register(HorizontalViewType())
.multiRegister(Message::class, object : MultiLink<Message> {
override fun link(data: Message): MoreViewType<Message>? {
if (data.me) {
return MessageOutViewType()
} else {
return MessageInViewType()
}
}
})
.renderWithAnimation()
.startAnimPosition(1)
.attachTo(complete_list)
- 默认 data <-> viewType 一对一关系的,我们不需要在注册的时候声明 data 数据类,因为在 ViewType 中已经确定了数据类型,不用重复声明
- 类似 im 界面, data <-> viewType 一对多关系的,我们使用
multiRegister
完成,需要显式声明 data,实现MultiLink
接口来做判断,这些操作都是在一个方法中完成 - 提供列表显示动画,并支持自定义
- 支持全局注册
- 全部都是链式调用,非常直观
4. 强大的 Kotlin
这个应该是最大的不同的, kotlin 真的是一门写起来让人很爽的语言,得益于 Kotlin ,MoreType 可以更加自如的操作数据,内置了以下一些方法:
- fun loadData(data: Any) :加载数据 object/list
- fun getData(position: Int) : Any :获取某一个数据
- fun removeAllData() :移除全部数据
- fun removeData(data: Any) :移除某一条数据
- fun removeData(position: Int) :根据 position 移除某一条数据
通过这些方法,可以更方便快速的操作数据,完成下拉刷新,上滑加载等功能,可以参考这里的实现CompleteActivity.kt
开始你会发现很像,确实 MultiType 的思路在我看来是目前有关组合布局显示上实践最好的,当然如果你去查大量源码,你会发现很多库都是这个思路,并不是 MultiType 独创,好的技术当然值得学习。
MoreType 的目的是为了更简洁的方便人们使用,当你看完 sample 中的示例代码,你会发现唯一的不同就是处处不同
😄