Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

与 MultiType 的异同 #1

Closed
appdev opened this issue Jul 19, 2017 · 1 comment
Closed

与 MultiType 的异同 #1

appdev opened this issue Jul 19, 2017 · 1 comment

Comments

@appdev
Copy link

appdev commented Jul 19, 2017

这个和MultiType有什么区别呢?

@werbhelius
Copy link
Owner

werbhelius commented Jul 19, 2017

@huclengyue
核心思想是一样的【数据驱动视图】,区别在实现和使用上

1. 我们最终是要形成一种数据与视图的对应关系,即 MoreType 的 data 和 viewType。

  • MultiType 在当时我看的时候,是使用 list 实现,通过相同的 index 形成一个对应关系。
  • MoerType 采用 SparseArrayCompat 实现,通过在 viewType 中返回的 layout 作为 key 来确定对应关系,在 Android 中布局是唯一的,也可以说一种布局代表一种视图。

2. 更简单的实现视图

只需要继承 MoerViewType<T: Any>() 并重写三个方法,这三个方法的目的也很明确

  • getViewLayout() : 返回视图的布局,当成唯一的 key 来和 data 确定关系,同时用于创建 ViewHolder
  • getViewModel() : 返回视图对应的数据类(data),即声明视图所对应的数据类
  • bindData () : 绑定数据,处理各种事件,内置点击事件实现方法

可以看到,我们并不用去重复写 ViewHolder,如果配合 kotlin-android-extensionsfindViewId 也省去了,下面是实现简单的聊天界面的 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 中的示例代码,你会发现唯一的不同就是处处不同

😄

@werbhelius werbhelius changed the title Kotlin版的MultiType 与 MultiType 的异同 Jul 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants