├── .editorconfig ├── .gitignore ├── Readme.md ├── annotation ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── quartack │ └── bdapter │ └── annotation │ ├── BdapterAnnotaionUtils.kt │ ├── BdapterViewHolder.kt │ └── OnBdapterViewHolderEventListener.kt ├── bdapter ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── libs │ └── annotation.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── quartack │ └── bdapter │ ├── Bdapter.kt │ ├── BdapterViewHolder.kt │ └── RecyclerViewBindingAdapters.kt ├── build.gradle ├── generator ├── .gitignore ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── quartack │ │ └── bdapter │ │ └── annotationprocessor │ │ ├── BdapterAnnotationProcessor.kt │ │ ├── job │ │ ├── Extensions.kt │ │ ├── Job.kt │ │ └── ViewHolderJob.kt │ │ └── printer │ │ ├── FilePrinter.kt │ │ └── ViewHolderPrinter.kt │ └── resources │ └── META-INF │ └── services │ └── javax.annotation.processing.Processor ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── resources ├── sample_drag.gif ├── sample_event.gif ├── sample_filter.gif ├── sample_grid.png ├── sample_in_recyclerview.gif ├── sample_multiple.png ├── sample_sort.gif ├── sample_tree.gif └── sample_update.gif └── settings.gradle /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | max_line_length = 120 11 | tab_width = 4 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | .idea 4 | .DS_Store 5 | /local.properties 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # welcome to bdapter! 2 | Hello! ***bdapter*** is made for developers who are tired of coding `RecyclerView.Adapter` and `RecyclerView.ViewHolder`. 3 | 4 | With ***bdapter*** You can use `RecyclerView` without implementation of `RecyclerView.Adapter` and `RecyclerView.ViewHolder` anymore, Also multiple viewHolder is works fine. 5 | 6 | And, ***bdapter*** supports `DataBinding` and `MVVM`. 7 | 8 | # samples 9 | ![](resources/sample_multiple.png) | ![](resources/sample_grid.png) | ![](./resources/sample_update.gif) 10 | :---: | :---: | :---: 11 | [multiple viewHolder](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/basic) | [any layoutManager](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/grid) | [update items](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/update) 12 | 13 | ![](resources/sample_tree.gif) | ![](./resources/sample_filter.gif) | ![](./resources/sample_sort.gif) 14 | :---: | :---: | :---: 15 | [tree](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/tree) | [filter](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/filter) | [sort](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/sort) 16 | 17 | ![](./resources/sample_in_recyclerview.gif) | ![](./resources/sample_drag.gif) | ![](./resources/sample_event.gif) 18 | :---: | :---: | :---: 19 | [recyclerView inside recyclerView](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/recycler_inside_recycler) | [drag](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/drag) | [event](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/event) 20 | 21 | # download 22 | [![](https://jitpack.io/v/quartack/bdapter.svg)](https://jitpack.io/#quartack/bdapter) 23 | ``` 24 | repositories { 25 | maven { url 'https://jitpack.io' }} 26 | } 27 | dependencies { 28 | implementation "com.github.quartack.bdapter:bdapter:0.9.3" 29 | kapt "com.github.quartack.bdapter:generator:0.9.3" 30 | } 31 | ``` 32 | # how to use 33 | ## model 34 | **MyModel.kt** 35 | ```kotlin 36 | @Keep 37 | @bdapterViewHolder( 38 | dataBinding = ViewholderMyModelBinding::class, 39 | viewModelClass = MyViewModel::class 40 | ) 41 | data class MyModel( 42 | val id: Int 43 | ) 44 | ``` 45 | Add `@Keep` and `@bdapterViewHolder` annotations in your model class. 46 | If you are using ProGuard's rule, `@Keep` can be omitted. 47 | 48 | ## view holder - layout 49 | **viewholder_my_model.xml** 50 | ```xml 51 | 52 | 53 | 54 | 57 | 60 | 61 | 65 | 66 | ``` 67 | Written in general `DataBinding` style. 68 | 69 | ## view model 70 | **MyViewModel.kt** 71 | ```kotlin 72 | class MyViewModel : ViewModel() { 73 | private val _items = MutableLiveData>().apply { 74 | value = listOf( 75 | MyModel(1), MyModel(2), MyModel(3) 76 | ) 77 | } 78 | val items: LiveData> 79 | get() = _items 80 | } 81 | ``` 82 | Create `items` it will be the source of RecyclerView. 83 | 84 | ***bdapter*** will update the RecyclerView if the value of the `items` changed. 👏 85 | 86 | ## activity - layout 87 | **activity_main.xml** 88 | ```xml 89 | 90 | 94 | 95 | 98 | 99 | 106 | 107 | ``` 108 | Written in general `DataBinding` style. 109 | Set a `viewModel.items` to `binding:bdapterItems` and `viewModel` to `binding:bdapterViewModel`. 110 | 111 | ## activity 112 | **MyActivity.kt** 113 | ```kotlin 114 | class MyActivity : AppCompatActivity() { 115 | private val viewModel by viewModels() 116 | 117 | override fun onCreate(savedInstanceState: Bundle?) { 118 | super.onCreate(savedInstanceState) 119 | initDataBinding() 120 | } 121 | 122 | private fun initDataBinding() { 123 | ActivityMainBinding.inflate(layoutInflater).also { 124 | it.viewModel = viewModel 125 | it.lifecycleOwner = this 126 | it.lifecycleOwner!!.lifecycle.addObserver(viewModel) 127 | setContentView(it.root) 128 | } 129 | } 130 | } 131 | ``` 132 | Written in general `DataBinding` style. 133 | 134 | ## complete! 135 | You used `RecyclerView` without implementing `RecyclerView.Adater` and `RecyclerView.ViewHolder` through ***bdapter***. 136 | 137 | # FAQ 138 | * Is multiple ViewHolder possible? 139 | -> **YEP** 140 | * Need code for `RecyclerView.ViewHolder` Class? 141 | -> **NOPE** 142 | * Need code for `RecyclerView.Adapter` Class? 143 | -> **NOPE** 144 | * No need for `RecyclerView.Adapter` logic? Like a add, edit, delete, sort, hide and etc for items. 145 | -> **NOPE, only manage items in ViewMoles** 146 | * Can I use my own the `DiffUtil`? 147 | -> **[SURE, checkout it sample project](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/diff_util)** 148 | * Can I change the variable name used in Databinding? 149 | -> **[SURE, checkout it sample project](https://github.com/quartack/bdapter_sample/tree/main/app/src/main/java/com/quartack/bdapter/sample/variable_name)** 150 | 151 | # license 152 | Apache License 2.0 153 | -------------------------------------------------------------------------------- /annotation/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /annotation/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java-library' 2 | apply plugin: 'kotlin' 3 | 4 | dependencies { 5 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 6 | } 7 | 8 | buildscript { 9 | repositories { 10 | jcenter() 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /annotation/src/main/java/com/quartack/bdapter/annotation/BdapterAnnotaionUtils.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotation 2 | 3 | import javax.lang.model.element.Element 4 | import javax.lang.model.element.ElementKind 5 | 6 | const val BDAPTER_VIEW_HOLDER_PACKAGE = "com.quartack.bdapter" 7 | const val BDAPTER_VIEW_HOLDER_CLASS = "BdapterViewHolder" 8 | 9 | fun Element.getPackageNameOfElement(): String { 10 | var item: Element = this 11 | while (item.kind !== ElementKind.PACKAGE) { 12 | item = item.enclosingElement 13 | } 14 | return item.toString() 15 | } 16 | 17 | fun createViewHolderClassName(element: Element) = 18 | createViewHolderClassName( 19 | element.toString() 20 | .replace(element.getPackageNameOfElement(), "") 21 | .replace(".", "") 22 | ) 23 | 24 | fun createViewHolderClassName(klass: Class) = 25 | createViewHolderClassName( 26 | klass.name.replace("$", "") 27 | ) 28 | 29 | fun createViewHolderClassName(modelClass: String) = 30 | "$modelClass$BDAPTER_VIEW_HOLDER_CLASS" 31 | -------------------------------------------------------------------------------- /annotation/src/main/java/com/quartack/bdapter/annotation/BdapterViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotation 2 | 3 | import kotlin.reflect.KClass 4 | 5 | @Target(AnnotationTarget.CLASS) 6 | @Retention(AnnotationRetention.RUNTIME) 7 | annotation class BdapterViewHolder( 8 | val dataBinding: KClass<*>, 9 | val viewModelClass: KClass<*>, 10 | val viewModelVariableName: String = "viewModel", 11 | val itemVariableName: String = "item", 12 | val eventListener: KClass> = 13 | EmptyBdapterViewHolderEventListener::class 14 | ) 15 | -------------------------------------------------------------------------------- /annotation/src/main/java/com/quartack/bdapter/annotation/OnBdapterViewHolderEventListener.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotation 2 | 3 | open class OnBdapterViewHolderEventListener { 4 | // From RecyclerView.Adapter#onBindViewHolder 5 | open fun onBindViewHolder(item: M, holder: V, viewModel: VM) { 6 | } 7 | 8 | // From RecyclerView.Adapter#onViewAttachedToWindow 9 | open fun onViewAttachedToWindow(item: M, holder: V, viewModel: VM) { 10 | } 11 | 12 | // From RecyclerView.Adapter#onViewDetachedFromWindow 13 | open fun onViewDetachedFromWindow(holder: V, viewModel: VM) { 14 | } 15 | 16 | // From RecyclerView.Adapter#onViewRecycled 17 | open fun onViewRecycled(holder: V) { 18 | } 19 | 20 | // From RecyclerView.Adapter#onFailedToRecycleView 21 | open fun onFailedToRecycleView(holder: V): Boolean { 22 | return false 23 | } 24 | } 25 | 26 | class EmptyBdapterViewHolderEventListener : OnBdapterViewHolderEventListener() 27 | -------------------------------------------------------------------------------- /bdapter/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /bdapter/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | 5 | android { 6 | compileSdkVersion 30 7 | buildToolsVersion "29.0.2" 8 | defaultConfig { 9 | minSdkVersion 16 10 | targetSdkVersion 30 11 | versionCode 1 12 | versionName rootProject.ext.version_name 13 | } 14 | 15 | buildFeatures { 16 | dataBinding true 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | lintOptions { 27 | abortOnError false 28 | } 29 | } 30 | 31 | dependencies { 32 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 33 | implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" 34 | 35 | implementation 'androidx.recyclerview:recyclerview:1.1.0' 36 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" 37 | 38 | api files('libs/annotation.jar') 39 | } 40 | 41 | buildscript { 42 | repositories { 43 | jcenter() 44 | } 45 | } 46 | 47 | apply plugin: 'maven-publish' 48 | afterEvaluate { 49 | publishing { 50 | publications { 51 | release(MavenPublication) { 52 | from components.release 53 | 54 | groupId = rootProject.ext.package_name 55 | artifactId = 'bdapter' 56 | version = rootProject.ext.version_name 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /bdapter/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/bdapter/consumer-rules.pro -------------------------------------------------------------------------------- /bdapter/libs/annotation.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/bdapter/libs/annotation.jar -------------------------------------------------------------------------------- /bdapter/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /bdapter/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /bdapter/src/main/java/com/quartack/bdapter/Bdapter.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter 2 | 3 | import android.view.LayoutInflater 4 | import android.view.ViewGroup 5 | import androidx.annotation.Keep 6 | import androidx.lifecycle.ViewModel 7 | import androidx.recyclerview.widget.DiffUtil 8 | import androidx.recyclerview.widget.ListAdapter 9 | import com.quartack.bdapter.annotation.createViewHolderClassName 10 | import java.util.concurrent.atomic.AtomicInteger 11 | import kotlin.reflect.KClass 12 | import kotlin.reflect.KFunction 13 | import kotlin.reflect.full.declaredFunctions 14 | import com.quartack.bdapter.annotation.BdapterViewHolder as BdapterViewHolderAnnotation 15 | 16 | val basicDiffUtil = object : DiffUtil.ItemCallback() { 17 | override fun areItemsTheSame(oldItem: Any, newItem: Any) = oldItem == newItem 18 | override fun areContentsTheSame(oldItem: Any, newItem: Any) = oldItem == newItem 19 | } 20 | 21 | @Keep 22 | @Suppress("UNCHECKED_CAST") 23 | class Bdapter( 24 | diffUtil: DiffUtil.ItemCallback 25 | ) : ListAdapter>(diffUtil) { 26 | var viewModel: ViewModel? = null 27 | 28 | private val viewTypeCounter = AtomicInteger(1) 29 | private val viewTypeMap: MutableMap, Int> = mutableMapOf() 30 | private val inflaterMap: MutableMap> = mutableMapOf() 31 | private val viewHolderMap: MutableMap>> = mutableMapOf() 32 | 33 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BdapterViewHolder { 34 | val inflater = LayoutInflater.from(parent.context) 35 | val binding = inflaterMap[viewType]!!.call(inflater, parent, false) 36 | return viewHolderMap[viewType]!!.constructors.first().call(binding) 37 | } 38 | 39 | public override fun getItem(position: Int): Any { 40 | return super.getItem(position) 41 | } 42 | 43 | override fun getItemViewType(position: Int): Int { 44 | return getItemViewType(getItem(position)::class.java) 45 | } 46 | 47 | fun getItemViewType(klass: Class<*>): Int { 48 | if (viewTypeMap[klass] == null) { 49 | with(klass.findBdapterViewHolderAnnotation()) { 50 | val viewTypeCode = viewTypeCounter.incrementAndGet() 51 | viewTypeMap[klass] = viewTypeCode 52 | inflaterMap[viewTypeCode] = dataBinding.findInflateFunction() 53 | viewHolderMap[viewTypeCode] = 54 | Class.forName(createViewHolderClassName(klass)).kotlin as KClass> 55 | } 56 | } 57 | 58 | return viewTypeMap[klass]!! 59 | } 60 | 61 | fun getViewHolderByItemType(viewType: Int) = viewHolderMap[viewType] 62 | 63 | override fun onBindViewHolder(holder: BdapterViewHolder, position: Int) { 64 | holder.onBindViewHolder( 65 | getItem(holder.adapterPosition) as M, 66 | holder, 67 | viewModel as VM 68 | ) 69 | } 70 | 71 | override fun onViewAttachedToWindow(holder: BdapterViewHolder) { 72 | holder.onViewAttachedToWindow( 73 | getItem(holder.adapterPosition) as M, 74 | holder, 75 | viewModel as VM 76 | ) 77 | } 78 | 79 | override fun onViewDetachedFromWindow(holder: BdapterViewHolder) { 80 | holder.onViewDetachedFromWindow(holder, viewModel as VM) 81 | } 82 | 83 | override fun onViewRecycled(holder: BdapterViewHolder) { 84 | holder.onViewRecycled(holder) 85 | } 86 | 87 | override fun onFailedToRecycleView(holder: BdapterViewHolder): Boolean { 88 | return holder.onFailedToRecycleView(holder) 89 | } 90 | 91 | private fun Class<*>.findBdapterViewHolderAnnotation() = 92 | annotations.firstOrNull { 93 | it is BdapterViewHolderAnnotation 94 | } as? BdapterViewHolderAnnotation 95 | ?: throw IllegalAccessException("Declare the @BdapterViewHolder annotation in the $canonicalName") 96 | 97 | private fun KClass<*>.findInflateFunction() = 98 | declaredFunctions.first { 99 | it.name == "inflate" && it.parameters.size == 3 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /bdapter/src/main/java/com/quartack/bdapter/BdapterViewHolder.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter 2 | 3 | import androidx.annotation.Keep 4 | import androidx.databinding.ViewDataBinding 5 | import androidx.lifecycle.ViewModel 6 | import androidx.recyclerview.widget.RecyclerView 7 | 8 | @Keep 9 | open class BdapterViewHolder( 10 | open val binding: ViewDataBinding 11 | ) : RecyclerView.ViewHolder(binding.root) { 12 | open fun onBindViewHolder(item: M, holder: BdapterViewHolder, viewModel: VM) { 13 | } 14 | 15 | open fun onViewAttachedToWindow(item: M, holder: BdapterViewHolder, viewModel: VM) { 16 | } 17 | 18 | open fun onViewDetachedFromWindow(holder: BdapterViewHolder, viewModel: VM) { 19 | } 20 | 21 | open fun onViewRecycled(holder: BdapterViewHolder) { 22 | } 23 | 24 | open fun onFailedToRecycleView(holder: BdapterViewHolder): Boolean { 25 | return false 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bdapter/src/main/java/com/quartack/bdapter/RecyclerViewBindingAdapters.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter 2 | 3 | import androidx.databinding.BindingAdapter 4 | import androidx.lifecycle.ViewModel 5 | import androidx.recyclerview.widget.DiffUtil 6 | import androidx.recyclerview.widget.LinearLayoutManager 7 | import androidx.recyclerview.widget.RecyclerView 8 | 9 | @BindingAdapter( 10 | "binding:bdapterItems", 11 | "binding:bdapterViewModel", 12 | "binding:bdapterDiffUtil", 13 | "binding:bdapterChangedItemsPosition", 14 | requireAll = false 15 | ) 16 | fun RecyclerView.initBdapter( 17 | items: List?, 18 | viewModel: ViewModel?, 19 | diffUtil: DiffUtil.ItemCallback?, 20 | changedItems: List? 21 | ) { 22 | initBindingAdapter(diffUtil) 23 | 24 | items?.let { 25 | with(adapter as Bdapter<*, *>) { 26 | submitList(items) 27 | } 28 | } 29 | 30 | viewModel?.let { 31 | with(adapter as Bdapter<*, *>) { 32 | this.viewModel = viewModel 33 | } 34 | } 35 | 36 | changedItems?.forEach { position -> 37 | (findViewHolderForAdapterPosition(position) as? BdapterViewHolder<*, *>)?.binding?.invalidateAll() 38 | } 39 | } 40 | 41 | private fun RecyclerView.initBindingAdapter(diffUtil: DiffUtil.ItemCallback?) { 42 | if (null == layoutManager) layoutManager = LinearLayoutManager(context) 43 | if (null == adapter) adapter = Bdapter(diffUtil ?: basicDiffUtil) 44 | } 45 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.4.21' 5 | ext.lifecycle_version = '2.3.0' 6 | ext.activity_version = "1.1.0" 7 | 8 | ext.version_name = "0.9.3" 9 | ext.package_name = "com.quartack.bdapter" 10 | 11 | repositories { 12 | google() 13 | jcenter() 14 | } 15 | dependencies { 16 | classpath 'com.android.tools.build:gradle:4.1.2' 17 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | google() 26 | jcenter() 27 | } 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /generator/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /generator/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java-library' 2 | apply plugin: 'kotlin' 3 | 4 | dependencies { 5 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 6 | 7 | compileOnly files('../bdapter/libs/annotation.jar') 8 | } 9 | 10 | buildscript { 11 | repositories { 12 | jcenter() 13 | } 14 | } 15 | 16 | apply plugin: 'maven-publish' 17 | afterEvaluate { 18 | publishing { 19 | publications { 20 | release(MavenPublication) { 21 | from components.java 22 | groupId = rootProject.ext.package_name 23 | artifactId = 'generator' 24 | version = rootProject.ext.version_name 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/BdapterAnnotationProcessor.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor 2 | 3 | import com.quartack.bdapter.annotationprocessor.job.ViewHolderJob 4 | import javax.annotation.processing.AbstractProcessor 5 | import javax.annotation.processing.RoundEnvironment 6 | import javax.lang.model.element.TypeElement 7 | 8 | class BdapterAnnotationProcessor : AbstractProcessor() { 9 | private val annotationJobs by lazy { 10 | setOf( 11 | ViewHolderJob(processingEnv) 12 | ) 13 | } 14 | 15 | override fun getSupportedAnnotationTypes() = 16 | annotationJobs 17 | .map { 18 | it.annotation.canonicalName 19 | }.toSet() 20 | 21 | override fun process( 22 | annotations: MutableSet?, 23 | roundEnv: RoundEnvironment 24 | ): Boolean { 25 | if (annotations.isNullOrEmpty()) return true 26 | 27 | val failed = annotationJobs.filter { 28 | !it.process(annotations, roundEnv) 29 | } 30 | 31 | return failed.isNotEmpty() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/job/Extensions.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor.job 2 | 3 | import javax.lang.model.element.TypeElement 4 | import javax.lang.model.type.DeclaredType 5 | import javax.lang.model.type.MirroredTypeException 6 | 7 | internal fun MirroredTypeException.toClassName(): String { 8 | val classTypeMirror = typeMirror as DeclaredType 9 | val classTypeElement = classTypeMirror.asElement() as TypeElement 10 | 11 | return classTypeElement.qualifiedName.toString() 12 | } 13 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/job/Job.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor.job 2 | 3 | import com.quartack.bdapter.annotationprocessor.printer.FilePrinter 4 | import javax.annotation.processing.ProcessingEnvironment 5 | import javax.annotation.processing.RoundEnvironment 6 | import javax.lang.model.element.Element 7 | import javax.lang.model.element.TypeElement 8 | import javax.tools.Diagnostic 9 | import javax.tools.StandardLocation 10 | 11 | abstract class Job( 12 | private val processingEnv: ProcessingEnvironment 13 | ) { 14 | abstract val annotation: Class 15 | 16 | fun process( 17 | annotations: MutableSet, 18 | roundEnv: RoundEnvironment 19 | ): Boolean = 20 | process( 21 | roundEnv.getElementsAnnotatedWith(annotation), 22 | annotations, 23 | roundEnv 24 | ) 25 | 26 | protected abstract fun process( 27 | elements: Set, 28 | annotations: MutableSet, 29 | roundEnv: RoundEnvironment 30 | ): Boolean 31 | 32 | protected fun throwErrorMessage( 33 | message: String, 34 | element: Element? = null 35 | ): Int { 36 | processingEnv.messager.printMessage( 37 | Diagnostic.Kind.ERROR, 38 | "${message}\r", 39 | element 40 | ) 41 | return -1 42 | } 43 | 44 | internal fun shouldPrint( 45 | printer: FilePrinter, 46 | element: Element 47 | ) { 48 | processingEnv.filer.createResource( 49 | StandardLocation.SOURCE_OUTPUT, 50 | printer.packageName, 51 | printer.fileName, 52 | element 53 | ).openWriter().use { 54 | it.write(printer.print()) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/job/ViewHolderJob.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor.job 2 | 3 | import com.quartack.bdapter.annotation.BdapterViewHolder 4 | import com.quartack.bdapter.annotation.createViewHolderClassName 5 | import com.quartack.bdapter.annotation.getPackageNameOfElement 6 | import com.quartack.bdapter.annotationprocessor.printer.ViewHolderPrinter 7 | import javax.annotation.processing.ProcessingEnvironment 8 | import javax.annotation.processing.RoundEnvironment 9 | import javax.lang.model.element.Element 10 | import javax.lang.model.element.TypeElement 11 | import javax.lang.model.type.MirroredTypeException 12 | 13 | class ViewHolderJob( 14 | processingEnv: ProcessingEnvironment 15 | ) : Job(processingEnv) { 16 | override val annotation = BdapterViewHolder::class.java 17 | 18 | override fun process( 19 | elements: Set, 20 | annotations: MutableSet, 21 | roundEnv: RoundEnvironment 22 | ): Boolean { 23 | elements.forEach { element -> 24 | ViewHolderPrinter( 25 | element.getPackageNameOfElement(), 26 | createViewHolderClassName(element), 27 | element.toString(), 28 | element.getViewModelClass(), 29 | element.getviewModelVariableName(), 30 | element.getItemVariableName(), 31 | element.getDataBindingClass(), 32 | element.getEventListenerClass() 33 | ).also { print -> 34 | shouldPrint(print, element) 35 | } 36 | } 37 | 38 | return true 39 | } 40 | 41 | private fun Element.getDataBindingClass() = 42 | try { 43 | getAnnotation(annotation).dataBinding.toString() 44 | } catch (e: MirroredTypeException) { 45 | e.toClassName() 46 | } 47 | 48 | private fun Element.getViewModelClass() = 49 | try { 50 | getAnnotation(annotation).viewModelClass.toString() 51 | } catch (e: MirroredTypeException) { 52 | e.toClassName() 53 | } 54 | 55 | private fun Element.getviewModelVariableName() = 56 | try { 57 | getAnnotation(annotation).viewModelVariableName 58 | } catch (e: MirroredTypeException) { 59 | e.toClassName() 60 | } 61 | 62 | private fun Element.getItemVariableName() = 63 | try { 64 | getAnnotation(annotation).itemVariableName 65 | } catch (e: MirroredTypeException) { 66 | e.toClassName() 67 | } 68 | 69 | private fun Element.getEventListenerClass() = 70 | try { 71 | getAnnotation(annotation).eventListener.toString() 72 | } catch (e: MirroredTypeException) { 73 | e.toClassName() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/printer/FilePrinter.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor.printer 2 | 3 | internal interface FilePrinter { 4 | val packageName: String 5 | val fileName: String 6 | 7 | fun print(): String 8 | } 9 | -------------------------------------------------------------------------------- /generator/src/main/java/com/quartack/bdapter/annotationprocessor/printer/ViewHolderPrinter.kt: -------------------------------------------------------------------------------- 1 | package com.quartack.bdapter.annotationprocessor.printer 2 | 3 | import com.quartack.bdapter.annotation.BDAPTER_VIEW_HOLDER_CLASS 4 | import com.quartack.bdapter.annotation.BDAPTER_VIEW_HOLDER_PACKAGE 5 | 6 | class ViewHolderPrinter( 7 | override val packageName: String, 8 | private val className: String, 9 | private val modelClassPath: String, 10 | private val viewModelClass: String, 11 | private val viewModelVariableName: String, 12 | private val itemVariableName: String, 13 | private val dataBinding: String, 14 | private val eventListener: String 15 | ) : FilePrinter { 16 | override val fileName = "$className.kt" 17 | 18 | override fun print() = 19 | """package $packageName 20 | 21 | import androidx.annotation.Keep 22 | import $BDAPTER_VIEW_HOLDER_PACKAGE.$BDAPTER_VIEW_HOLDER_CLASS 23 | import $modelClassPath as Model 24 | import $dataBinding as DataBinding 25 | import $viewModelClass as ViewModel 26 | import $eventListener as EventListener 27 | 28 | @Keep 29 | class $className(override val binding: DataBinding) : 30 | $BDAPTER_VIEW_HOLDER_CLASS(binding) { 31 | 32 | private val eventListener = EventListener() 33 | 34 | override fun onBindViewHolder( 35 | item: Model, 36 | holder: BdapterViewHolder, 37 | viewModel: ViewModel 38 | ) { 39 | binding.$itemVariableName = item 40 | binding.$viewModelVariableName = viewModel 41 | binding.executePendingBindings() 42 | 43 | eventListener.onBindViewHolder(item, holder as $className, viewModel) 44 | } 45 | 46 | override fun onViewAttachedToWindow( 47 | item: Model, 48 | holder: BdapterViewHolder, 49 | viewModel: ViewModel 50 | ) { 51 | eventListener.onViewAttachedToWindow(item, holder as $className, viewModel) 52 | } 53 | 54 | override fun onViewDetachedFromWindow( 55 | holder: BdapterViewHolder, 56 | viewModel: ViewModel 57 | ) { 58 | eventListener.onViewDetachedFromWindow(holder as $className, viewModel) 59 | } 60 | 61 | override fun onViewRecycled(holder: BdapterViewHolder) { 62 | eventListener.onViewRecycled(holder as $className) 63 | } 64 | 65 | override fun onFailedToRecycleView(holder: BdapterViewHolder): Boolean { 66 | return eventListener.onFailedToRecycleView(holder as $className) 67 | } 68 | } 69 | """ 70 | } 71 | -------------------------------------------------------------------------------- /generator/src/main/resources/META-INF/services/javax.annotation.processing.Processor: -------------------------------------------------------------------------------- 1 | com.quartack.bdapter.annotationprocessor.BdapterAnnotationProcessor -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 07 23:22:13 KST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /resources/sample_drag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_drag.gif -------------------------------------------------------------------------------- /resources/sample_event.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_event.gif -------------------------------------------------------------------------------- /resources/sample_filter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_filter.gif -------------------------------------------------------------------------------- /resources/sample_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_grid.png -------------------------------------------------------------------------------- /resources/sample_in_recyclerview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_in_recyclerview.gif -------------------------------------------------------------------------------- /resources/sample_multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_multiple.png -------------------------------------------------------------------------------- /resources/sample_sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_sort.gif -------------------------------------------------------------------------------- /resources/sample_tree.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_tree.gif -------------------------------------------------------------------------------- /resources/sample_update.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quartack/bdapter/6f20df01cedec709dab4b3534a554dd7daac7bfe/resources/sample_update.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':annotation', ':generator', ':bdapter' 2 | --------------------------------------------------------------------------------