aboutsummaryrefslogtreecommitdiff
path: root/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt
blob: b2b0f262d7d5b4ffec67a3a4577d4257b6265bbd (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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 * Copyright 2019 Allan Wang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
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)
}