aboutsummaryrefslogtreecommitdiff
path: root/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt
blob: d800fcde3d75584b80d4a407b86e0247f54afee3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package ca.allanwang.fastadapter.databinding

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.RecyclerView
import ca.allanwang.kau.logging.KL
import com.mikepenz.fastadapter.FastAdapter
import com.mikepenz.fastadapter.GenericItem
import com.mikepenz.fastadapter.items.AbstractItem
import com.mikepenz.fastadapter.listeners.ClickEventHook

interface VhModel {
    fun vh(): GenericItem
}

abstract class BindingItem<Binding : ViewDataBinding>(open val data: Any?) :
    AbstractItem<BindingItem.ViewHolder>(),
    BindingLayout<Binding> {

    override val type: Int
        get() = layoutRes

    override fun createView(ctx: Context, parent: ViewGroup?): View {
        val binding: ViewDataBinding = DataBindingUtil.inflate(
            LayoutInflater.from(ctx),
            layoutRes, parent,
            false
        )
        return binding.root
    }

    fun getBinding(holder: ViewHolder): Binding? =
        DataBindingUtil.getBinding<Binding>(holder.itemView)

    final override fun bindView(holder: ViewHolder, payloads: MutableList<Any>) {
        super.bindView(holder, payloads)
        val binding = getBinding(holder) ?: return
        binding.bindView(holder, payloads)
        binding.executePendingBindings()
    }

    abstract fun Binding.bindView(holder: ViewHolder, payloads: MutableList<Any>)

    final override fun unbindView(holder: ViewHolder) {
        super.unbindView(holder)
        val binding = DataBindingUtil.getBinding<Binding>(holder.itemView) ?: return
        binding.unbindView(holder)
        binding.unbind()
    }

    open fun Binding.unbindView(holder: ViewHolder) {}

    final override fun getViewHolder(v: View): ViewHolder = ViewHolder(v, layoutRes)

    override fun failedToRecycle(holder: ViewHolder): Boolean {
        KL.e { "Failed to recycle" }
        return super.failedToRecycle(holder)
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is BindingItem<*>) return false
        return identifier == other.identifier && data == other.data
    }

    override fun hashCode(): Int = data.hashCode()

    class ViewHolder(itemView: View, internal val layoutRes: Int) :
        RecyclerView.ViewHolder(itemView)
}

interface BindingLayout<Binding : ViewDataBinding> {
    val layoutRes: Int
}

abstract class BindingClickEventHook<Binding : ViewDataBinding, Item : BindingItem<Binding>>(val identifier: BindingLayout<Binding>) :
    ClickEventHook<Item>() {

    private fun RecyclerView.ViewHolder.binding(): Binding? {
        val holder = this as? BindingItem.ViewHolder ?: return null
        if (holder.layoutRes != identifier.layoutRes) {
            return null
        }
        return DataBindingUtil.getBinding(itemView)
    }

    final override fun onBind(viewHolder: RecyclerView.ViewHolder): View? =
        viewHolder.binding()?.onBind(viewHolder) ?: super.onBind(viewHolder)

    open fun Binding.onBind(viewHolder: RecyclerView.ViewHolder): View? = super.onBind(viewHolder)

    final override fun onBindMany(viewHolder: RecyclerView.ViewHolder): List<View>? =
        viewHolder.binding()?.onBindMany(viewHolder) ?: super.onBindMany(viewHolder)

    open fun Binding.onBindMany(viewHolder: RecyclerView.ViewHolder): List<View>? =
        super.onBindMany(viewHolder)

    final override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<Item>, item: Item) {
        val binding: Binding = DataBindingUtil.findBinding(v) ?: return
        binding.onClick(v, position, fastAdapter, item)
    }

    abstract fun Binding.onClick(v: View, position: Int, fastAdapter: FastAdapter<Item>, item: Item)
}