From 3f144bdbeeda6057d244b6a6eabff7b1f73d32ba Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 14 Sep 2019 13:05:03 -0700 Subject: Add initial binding --- build.gradle | 6 +- fastadapter-databinding/.gitignore | 1 + fastadapter-databinding/build.gradle | 21 ++++ fastadapter-databinding/consumer-rules.pro | 0 fastadapter-databinding/proguard-rules.pro | 21 ++++ .../src/main/AndroidManifest.xml | 1 + .../fastadapter/databinding/BindingItem.kt | 122 +++++++++++++++++++++ .../fastadapter/databinding/FastBindingAdapter.kt | 45 ++++++++ settings.gradle | 1 + 9 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 fastadapter-databinding/.gitignore create mode 100644 fastadapter-databinding/build.gradle create mode 100644 fastadapter-databinding/consumer-rules.pro create mode 100644 fastadapter-databinding/proguard-rules.pro create mode 100644 fastadapter-databinding/src/main/AndroidManifest.xml create mode 100644 fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt create mode 100644 fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/FastBindingAdapter.kt diff --git a/build.gradle b/build.gradle index bc5fadf..e9c7d86 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,9 @@ import kau.ChangelogGenerator import kau.Plugins -buildscript { +buildscript { + ext.kotlin_version = '1.3.41' + repositories { google() jcenter() @@ -17,7 +19,7 @@ buildscript { classpath Plugins.dexCount classpath Plugins.gitVersion classpath Plugins.spotless - } + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } wrapper.setDistributionType(Wrapper.DistributionType.ALL) } diff --git a/fastadapter-databinding/.gitignore b/fastadapter-databinding/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/fastadapter-databinding/.gitignore @@ -0,0 +1 @@ +/build diff --git a/fastadapter-databinding/build.gradle b/fastadapter-databinding/build.gradle new file mode 100644 index 0000000..aefb22e --- /dev/null +++ b/fastadapter-databinding/build.gradle @@ -0,0 +1,21 @@ +import kau.Dependencies +import kau.Versions + +ext.kauSubModuleMinSdk = Versions.coreMinSdk + +apply from: '../android-lib.gradle' + +android { + dataBinding { + enabled = true + } +} + +dependencies { + implementation project(':core') + + api Dependencies.fastAdapter + api Dependencies.fastAdapter("utils") +} + +apply from: '../artifacts.gradle' diff --git a/fastadapter-databinding/consumer-rules.pro b/fastadapter-databinding/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/fastadapter-databinding/proguard-rules.pro b/fastadapter-databinding/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/fastadapter-databinding/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/fastadapter-databinding/src/main/AndroidManifest.xml b/fastadapter-databinding/src/main/AndroidManifest.xml new file mode 100644 index 0000000..acd1012 --- /dev/null +++ b/fastadapter-databinding/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt b/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt new file mode 100644 index 0000000..e52838b --- /dev/null +++ b/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/BindingItem.kt @@ -0,0 +1,122 @@ +package ca.allanwang.fastadapter.databinding + + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding +import androidx.recyclerview.widget.RecyclerView +import ca.allanwang.gitdroid.logger.L +import ca.allanwang.gitdroid.views.BR +import com.bumptech.glide.Glide +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.items.AbstractItem +import com.mikepenz.fastadapter.listeners.ClickEventHook + +typealias GenericBindingItem = BindingItem<*> + +abstract class BindingItem(open val data: Any?) : AbstractItem(), + BindingLayout { + + 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, + null + ) + return binding.root + } + + final override fun bindView(holder: ViewHolder, payloads: MutableList) { + super.bindView(holder, payloads) + val binding = DataBindingUtil.getBinding(holder.itemView) ?: return + binding.bindView(holder, payloads) + binding.executePendingBindings() + } + + open fun Binding.bindView(holder: ViewHolder, payloads: MutableList) { + setVariable(BR.model, data) + } + + final override fun unbindView(holder: ViewHolder) { + super.unbindView(holder) + val binding = DataBindingUtil.getBinding(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 { + L.e { "Failed to recycle" } + return super.failedToRecycle(holder) + } + + companion object { + @JvmStatic + protected fun unbindGlide(vararg imageView: ImageView) { + if (imageView.isEmpty()) { + return + } + val manager = Glide.with(imageView.first().context) + imageView.forEach { manager.clear(it) } + } + + @JvmStatic + protected fun unbind(vararg imageView: ImageView) { + imageView.forEach { it.setImageDrawable(null) } + } + + @JvmStatic + protected fun unbind(vararg textView: TextView) { + textView.forEach { it.text = null } + } + } + + class ViewHolder(itemView: View, internal val layoutRes: Int) : RecyclerView.ViewHolder(itemView) + +} + +interface BindingLayout { + val layoutRes: Int +} + + +abstract class BindingClickEventHook>(val identifier: BindingLayout) : + ClickEventHook() { + + 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? = + viewHolder.binding()?.onBindMany(viewHolder) ?: super.onBindMany(viewHolder) + + open fun Binding.onBindMany(viewHolder: RecyclerView.ViewHolder): List? = super.onBindMany(viewHolder) + + final override fun onClick(v: View, position: Int, fastAdapter: FastAdapter, 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) +} \ No newline at end of file diff --git a/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/FastBindingAdapter.kt b/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/FastBindingAdapter.kt new file mode 100644 index 0000000..2270b5d --- /dev/null +++ b/fastadapter-databinding/src/main/kotlin/ca/allanwang/fastadapter/databinding/FastBindingAdapter.kt @@ -0,0 +1,45 @@ +package ca.allanwang.fastadapter.databinding + +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.IAdapter +import com.mikepenz.fastadapter.IItemAdapter +import com.mikepenz.fastadapter.adapters.ItemAdapter +import com.mikepenz.fastadapter.diff.FastAdapterDiffUtil + +class FastBindingAdapter private constructor(private val adapter: ItemAdapter) : + FastAdapter(), + IItemAdapter by adapter { + + constructor() : this(ItemAdapter()) + + var lastClearTime: Long = -1 + + init { + super.addAdapter(0, adapter) + } + + override fun clear(): FastBindingAdapter { + if (itemCount != 0) { + adapter.clear() + lastClearTime = System.currentTimeMillis() + } + return this + } + + override fun > addAdapter( + index: Int, + adapter: A + ): FastAdapter { + throw IllegalArgumentException("FastBindingAdapter only allows one adapter") + } + + fun setWithDiff(items: List, detectMoves: Boolean = true) { + FastAdapterDiffUtil.set( + adapter, + items, + null, + detectMoves + ) + } + +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 42d498e..0ec0606 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,7 @@ include ':core', ':about', ':adapter', ':fastadapter', + ':fastadapter-databinding', ':colorpicker', ':mediapicker', ':kpref-activity', -- cgit v1.2.3