{"id":22650582,"url":"https://github.com/bleacherreport/velocidapter","last_synced_at":"2026-03-07T18:04:15.924Z","repository":{"id":33595759,"uuid":"155460913","full_name":"bleacherreport/Velocidapter","owner":"bleacherreport","description":"A Databinding Alternative for Adapters","archived":false,"fork":false,"pushed_at":"2021-12-02T22:51:33.000Z","size":425,"stargazers_count":13,"open_issues_count":2,"forks_count":4,"subscribers_count":31,"default_branch":"master","last_synced_at":"2025-10-26T07:45:56.981Z","etag":null,"topics":["android","android-architecture","android-library","annotation-processor","kotlin-android","kotlin-android-extensions","recyclerview"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bleacherreport.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-30T21:51:13.000Z","updated_at":"2024-07-11T17:44:11.000Z","dependencies_parsed_at":"2022-09-17T21:32:29.056Z","dependency_job_id":null,"html_url":"https://github.com/bleacherreport/Velocidapter","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bleacherreport/Velocidapter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleacherreport%2FVelocidapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleacherreport%2FVelocidapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleacherreport%2FVelocidapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleacherreport%2FVelocidapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bleacherreport","download_url":"https://codeload.github.com/bleacherreport/Velocidapter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bleacherreport%2FVelocidapter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30225456,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T17:00:40.062Z","status":"ssl_error","status_checked_at":"2026-03-07T17:00:39.026Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-architecture","android-library","annotation-processor","kotlin-android","kotlin-android-extensions","recyclerview"],"created_at":"2024-12-09T08:35:03.106Z","updated_at":"2026-03-07T18:04:15.896Z","avatar_url":"https://github.com/bleacherreport.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Velocidapter\n\n[ ![Download](https://img.shields.io/github/v/release/bleacherreport/Velocidapter?label=Github%20Maven%20Version\u0026logo=github) ](https://github.com/orgs/bleacherreport/packages?repo_name=Velocidapter)\n\nA 100% Kotlin functional adapter code generation library\n\nThe RecyclerView Adapter should do 2 things: inflate your ViewHolders in the right order and bind them with the right data. Maybe you like writing the same boilerplate functions for different ViewHolders and view types, but for everyone else, there's Velocidapter.\n\nVelocidapter writes your Adapters for you, and all you have to give it is ViewHolders and their data.\n\n## Installation\n\nVelocidapter is available on GitHub Packages. Replace `{version}` below with\u0026nbsp;  [ ![Download](https://img.shields.io/github/v/release/bleacherreport/Velocidapter?label=) ](https://github.com/orgs/bleacherreport/packages?repo_name=Velocidapter)\u0026nbsp; (remove the prefix `v`).\n```groovy\nrepositories {\n    mavenCentral()\n}\n\nkapt 'com.bleacherreport.velocidapter:velocidapter:{version}'\nimplementation 'com.bleacherreport.velocidapter:velocidapter-android:{version}'\n```\n If you don't have `kapt` set up in your project already, follow [this](https://kotlinlang.org/docs/reference/kapt.html).\n \n## Usage\n\nVelocidapter uses kapt annotation processing to generate adapter classes and type safe lists for you to update View Holders.\n\n### Short Version\n\nFor all you folks that just want to jump in, below is an example of a simple screen with one adapter that has two different ViewHolders and data types. The next section breaks this example down.\n\n```kotlin\nconst val MyAdapter = \"MyAdapter\"\n\nclass MainActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n\n        val dataTarget = recyclerView.withLinearLayoutManager()\n                                     .attachMyAdapter()\n        val dataList = MyAdapterDataList()\n        dataList.add(\"hello\")\n        dataList.add(123)\n        dataTarget.updateDataset(dataList)\n    }\n}\n```\n\n```kotlin\n@ViewHolder(adapters = [MyAdapter])\nfun MyStringViewBinding.bind(data: String) {\n    textView.text = \"$data world\"\n}\n```\n\n```kotlin\n@ViewHolder(adapters = [MyAdapter])\nclass NumberViewHolder(val binding : MyNumberViewBinding) : \n        RecyclerView.ViewHolder(binding.root) {\n    \n    @Bind\n    fun bindModel(data: Int) {\n        binding.textView.text = \"$data 456\"\n    }\n}\n```\n\n# Long Version\n\nDecide a name for your adapter. This is the name your generated classes will be based on.\n\n```kotlin\nconst val MyAdapter = \"MyAdapter\"\n```\n\n### ViewHolder Class Example\n-----\nNext, create your ViewHolder. Your Adapter is bound to one or more Adapters using the `adapters` field in the `@ViewHolder` annotation (you see here we use the string defined above). You also specify the `ViewBinding` inside the constructor\n\n```kotlin\n@ViewHolder(adapters = [MyAdapter])\nclass StringViewHolder(val binding : MyViewBinding, val alsoInclude : CustomClass) : \n        RecyclerView.ViewHolder(binding.root)\n```\n\nYou'll notice there is also a paramater of type `CustomClass` in the example above.  You can include as many parameters in the constructor as you'd like, and the auto generated adapter will also require those paramters on creation.\n\nYour ViewHolder needs to have a way to be bound with data. You need to annotate any function within the ViewHolder with `@Bind`. The function can have any name and can take one or two parameters.\n1. The first argument must the data model you bind with\n2. **Optional** the Second argument may be `position: Int`\n3. **Optional** the function may extend the `ViewBinding` of the `ViewHolder`\n\n```kotlin\n@Bind\nfun MyViewBinding.bindModel(data: StringViewHolderModel, position: Int) {\n    textView.text = \"${data.text} world\"\n}\n```\n\n### ViewBinding Extension Function Example\n-----\nNext, create your `ViewBinding` Extension Function. Your Adapter is bound to one or more Adapters using the `adapters` field in the `@ViewHolder` annotation (you see here we use the string defined above).\n\nYour `ViewBinding` extension function can have any name and can take one parameter.\n1. The method must extend a `ViewBinding`\n2. The next argument must be the data model you bind with\n\n```kotlin\n@ViewHolder(adapters = [MyAdapter])\nfun MyViewBinding.bindModel(data: StringViewBindingModel) {\n    textView.text = \"${data.text} world\"\n}\n\nobject ViewBindingsUtil {\n    @ViewHolder(adapters = [MyAdapter])\n    fun MyViewBinding.bindModel(data: StringViewBindingObjectModel) {\n        textView.text = \"${data.text} world\"\n    }\n}\n```\n\n### Build\n-----\n\nNow you should be ready to run a quick build of your project, and the Adapter will be generated for you. Now you can bind it to it's RecyclerView, likely somewhere in your activity or fragment. The function `attachMyAdapter()` is generated based on your adapter name and will return a `AdapterDataTarget`\n\n```kotlin\nval dataTarget = recyclerView.withLinearLayoutManager()\n                             .attachMyAdapter()\n```\n\nNow of course you need to give this adapter the data it should show. This data should come in a generated type. For this example it's called `MyAdapterDataList`, a type safe wrapper around a list.\n\n```kotlin\nval dataList = MyAdapterDataList()\n```\n\nYou can only add data to this list that conforms to the data that's able to be bound by the ViewHolders in this Adapter. For this example, since the Adapter only has one ViewHolder, which takes `Strings`, the `add()` functions on this DataList only accepts Strings.\n\n```kotlin\n// ViewHolder Class Example\ndataList.addListOfStringViewHolderModel(\n    listOf(\n        StringViewHolderModel(\"hello\"), \n        StringViewHolderModel(\"world\")\n    )\n)\n// ViewBinding Top Level Extension Function Example\ndataList.addListOfStringViewBindingModel(\n    listOf(\n        StringViewBindingModel(\"hello\"), \n        StringViewBindingModel(\"world\")\n    )\n)\n// ViewBinding Object Member Extension Function Example\ndataList.add(StringViewBindingObjectModel(\"hello\"))\ndataList.add(StringViewBindingObjectModel(\"world\"))\n```\n\nThis list is passed to the Adapter using the `AdapterDataTarget` update function `updateDataset()`. This function should be the primary way to update data. For this data set, since it's not `DiffComparable`, it will simply reset the data and call `notifyDataSetChanged()` on the Adapter. For more complex usages, see below.\n\n```kotlin\ndataTarget.updateDataset(dataList)\n```\n\nAnd that's it! And if you wanted to add another ViewHolder that takes `Ints` for instance, you can just build the ViewHolder, bind it to the same Adapter, and start passing in `Ints` to the `MyAdapterDataList`. Easy as that.\n\n## AdapterDataTarget Functions\n\nTo clear all items from an `AdapterDataTarget` just call `setEmpty()`\n```kotlin\ndataTarget.setEmpty()\n```\n\nTo reset all items, just call `resetData()`\n```kotlin\ndataTarget.resetData(datalist)\n```\n\nWhat if I want to update a few dataset items without resetting the whole list? First we will need all dataset types within the list to implement the `DiffComparable` interface. Our class must implement an `equals()` method that checks for exact internal equality and an `isSame()` method that check for equality via unique identifier\n\n```kotlin\ndata class DiffPoko(val id : Int, val time: Long) : DiffComparable {\n    override fun isSame(that: Any): Boolean {\n        return if(that is DiffPoko) {\n            id == that.id\n        } else {\n            false\n        }\n    }\n}\n```\n\nWe then need to enable list diffing on the `AdapterDataTarget`\n\n```kotlin\nval target = recyclerView.withLinearLayoutManager()\n                         .attachDiffTypeAdapter()\n                         .enableDiff()\n```\n\nOnce that's enabled, all we need to do is update the list using\n\n```kotlin\ntarget.updateDataset(newDataList)\n```\n\nVelocidapter will update, delete, and move items as needed based off of the DiffComparable check. Failure to implement `DiffComparable` for all data types or forgetting to call `enableDiff()` will cause `updateDataset()` to function as `resetData()`\n\n## LiveData\n\n`LiveData` is supported out of the box as well.\n\n```kotlin\nval liveData = viewModel.getLiveData()\nrecyclerView.withLinearLayoutManager()\n            .attachMyAdapter()\n            .observeLiveData(liveData, lifecycleOwner)\n```\nor\n```kotlin\nval observer = recyclerView.withLinearLayoutManager()\n                           .attachMyAdapter()\n                           .observeLiveDataForever(liveData)\n```\n\n## Contribution\nIssues and PRs are welcome!\n\n\n## License\n```\nCopyright 2018 Bleacher Report\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbleacherreport%2Fvelocidapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbleacherreport%2Fvelocidapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbleacherreport%2Fvelocidapter/lists"}