FastAdapter
The FastAdapter is here to simplify creating adapters for RecyclerViews. Don't worry about the adapter anymore. Just write the logic for how your view/item should look like, and you are done.
It's blazing fast, minimizing the code you need to write, and is easy to extend.
What's included 🚀 •
Setup 🛠️ •
Migration Guide 🧬 •
Used by •
Sample App
What's included 🚀
Preview
Screenshots 🎉
Setup
Latest releases 🛠
- Kotlin | v5.7.0
- [Deprecated] Java && AndroidX | v3.3.1
- [Deprecated] Java && AppCompat | v3.2.9
Provide the gradle dependency
The library is split up into core, commons, and extensions. The core functions are included in the following dependency.
implementation "com.mikepenz:fastadapter:${latestFastAdapterRelease}"
implementation "androidx.appcompat:appcompat:${androidX}"
implementation "androidx.recyclerview:recyclerview:${androidX}"
Expandable support is included and can be added via this
implementation "com.mikepenz:fastadapter-extensions-expandable:${latestFastAdapterRelease}"
Many helper classes are included in the following dependency.
implementation "com.mikepenz:fastadapter-extensions-binding:${latestFastAdapterRelease}" // view binding helpers
implementation "com.mikepenz:fastadapter-extensions-diff:${latestFastAdapterRelease}" // diff util helpers
implementation "com.mikepenz:fastadapter-extensions-drag:${latestFastAdapterRelease}" // drag support
implementation "com.mikepenz:fastadapter-extensions-paged:${latestFastAdapterRelease}" // paging support
implementation "com.mikepenz:fastadapter-extensions-scroll:${latestFastAdapterRelease}" // scroll helpers
implementation "com.mikepenz:fastadapter-extensions-swipe:${latestFastAdapterRelease}" // swipe support
implementation "com.mikepenz:fastadapter-extensions-ui:${latestFastAdapterRelease}" // pre-defined ui components
implementation "com.mikepenz:fastadapter-extensions-utils:${latestFastAdapterRelease}" // needs the `expandable`, `drag` and `scroll` extension.
// required for the ui components and the utils
implementation "com.google.android.material:material:${androidX}"
How to use
1. Implement your item
1a. Implement your item as usual (the easy way)
Just create a class which extends the AbstractItem
as shown below. Implement the methods, and your item is ready.
open class SimpleItem : AbstractItem<SimpleItem.ViewHolder>() {
var name: String? = null
var description: String? = null
override val type: Int
get() = R.id.fastadapter_sample_item_id
override val layoutRes: Int
get() = R.layout.sample_item
override fun getViewHolder(v: View): ViewHolder {
return ViewHolder(v)
}
class ViewHolder(view: View) : FastAdapter.ViewHolder<SimpleItem>(view) {
var name: TextView = view.findViewById(R.id.material_drawer_name)
var description: TextView = view.findViewById(R.id.material_drawer_description)
override fun bindView(item: SimpleItem, payloads: List<Any>) {
name.text = item.name
description.text = item.name
}
override fun unbindView(item: SimpleItem) {
name.text = null
description.text = null
}
}
}
1b. Implement item with ViewBinding (the easiest way)
class BindingIconItem : AbstractBindingItem<IconItemBinding>() {
var name: String? = null
override val type: Int
get() = R.id.fastadapter_icon_item_id
override fun bindView(binding: IconItemBinding, payloads: List<Any>) {
binding.name.text = name
}
override fun createBinding(inflater: LayoutInflater, parent: ViewGroup?): IconItemBinding {
return IconItemBinding.inflate(inflater, parent, false)
}
}
Use the binding
extension dependency in your application for this.
2. Set the Adapter to the RecyclerView
val itemAdapter = ItemAdapter<SimpleItem>()
val fastAdapter = FastAdapter.with(itemAdapter)
recyclerView.setAdapter(fastAdapter)
itemAdapter.add(ITEMS)
3. Extensions
By default the FastAdapter
only provides basic functionality, which comes with the abstraction of items as Item
and Model
.
And the general functionality of adding/removing/modifying elements. To enable selections, or expandables the provided extensions need to be activated.
3.1. SelectExtension
val selectExtension = fastAdapter.getSelectExtension()
selectExtension.isSelectable = true
selectExtension.multiSelect = true
selectExtension.selectOnLongClick = false
3.2. ExpandableExtension
This requires the fastadapter-extensions-expandable
extension.
val expandableExtension = fastAdapter.getExpandableExtension()
expandableExtension.isOnlyOneExpandedItem = true
For further details scroll down to the ExpandableItems
(under advanced usage) section.
3. Click listener
fastAdapter.onClickListener = { view, adapter, item, position ->
false
}
4. Click listeners for views inside your item
fastAdapter.addEventHook(object : ClickEventHook<SimpleImageItem>() {
override fun onBind(viewHolder: RecyclerView.ViewHolder): View? {
return if (viewHolder is SimpleImageItem.ViewHolder) {
viewHolder.viewWhichReactsOnClick
} else {
null
}
}
override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<SimpleImageItem>, item: SimpleImageItem) {
}
})
5. Filter
itemAdapter.filter("yourSearchTerm")
itemAdapter.itemFilter.filterPredicate = { item: SimpleItem, constraint: CharSequence? ->
item.name?.text.toString().contains(constraint.toString(), ignoreCase = true)
}
filter()
should return true for items to be retained and false for items to be removed.
6. Drag and drop
This requires the fastadapter-extensions-drag
extension.
First, attach ItemTouchHelper
to RecyclerView.
val dragCallback = SimpleDragCallback()
val touchHelper = ItemTouchHelper(dragCallback)
touchHelper.attachToRecyclerView(recyclerView)
Implement ItemTouchCallback
interface in your Activity, and override the itemTouchOnMove()
method.
override fun itemTouchOnMove(oldPosition: Int, newPosition: Int): Boolean {
DragDropUtil.onMove(fastItemAdapter.itemAdapter, oldPosition, newPosition)
return true
}
Start by initializing your adapters:
val headerAdapter = ItemAdapter<Header>()
Initialize a Model FastAdapter:
val itemAdapter = GenericItemAdapter()
Finally, set the adapter:
val fastAdapter: GenericFastAdapter = FastAdapter.with(headerAdapter, itemAdapter)
recyclerView.setAdapter(fastAdapter)
8. Infinite (endless) scrolling
Create a FooterAdapter. We need this to display a loading ProgressBar at the end of our list. (Don't forget to pass it into FastAdapter.with(..)
)
val footerAdapter = ItemAdapter<ProgressItem>()
Keep in mind that ProgressItem is provided by FastAdapter’s extensions.
recyclerView.addOnScrollListener(object : EndlessRecyclerOnScrollListener(footerAdapter) {
override fun onLoadMore(currentPage: Int) {
footerAdapter.clear()
footerAdapter.add(ProgressItem())
itemAdapter.add(NEWITEMS)
}
})
For the complete tutorial and more features such as multi-select and CAB check out the sample app.
Advanced Usage
Proguard
- As of v2.5.0 there are no more known requirements to use the
FastAdapter
with Proguard
ExpandableItems
The FastAdapter
comes with support for expandable items. After adding the dependency set up the Expandable
extension via:
val expandableExtension = fastAdapter.getExpandableExtension()
Expandable items have to implement the IExpandable
interface, and the sub items the ISubItem
interface. This allows better support.
The sample app provides sample implementations of those. (Those in the sample are kept Model which allows them to be used with different parent / subitems)
As of the way how SubItems
and their state are handled it is highly recommended to use the identifier
based StateManagement
. Just add withPositionBasedStateManagement(false)
to your FastAdapter
setup.
A simple item just needs to extend from the AbstractExpandableItem
and provide the ViewHolder
as type.
open class SimpleSubExpandableItem : AbstractExpandableItem<SimpleSubExpandableItem.ViewHolder>() {
}
// See the SimpleSubExpandableItem.kt
of the sample application for more details.
Articles
Used by
Mike Penz:
Developed By
-
Mike Penz
-
Fabian Terhorst
Contributors
This free, open source software was also made possible by a group of volunteers that put many hours of hard work into it. See the CONTRIBUTORS.md file for details.
Special mentions
A special thanks to the very active contributors who added many improvements to this library.
License
Copyright 2021 Mike Penz
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.