Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.avito-tech:Konveyor:0.42.2'
}
dependencies {
implementation("com.github.avito-tech:Konveyor:0.42.2")
}
<dependency>
<groupId>com.github.avito-tech</groupId>
<artifactId>Konveyor</artifactId>
<version>0.42.2</version>
</dependency>
libraryDependencies += "com.github.avito-tech" % "Konveyor" % "0.42.2"
:dependencies [[com.github.avito-tech/Konveyor "0.42.2"]]
Konveyor is a tiny library which intends to battle RecyclerView.Adapter
Hell by introducing "Composition over inheritance"
approach when dealing with RecyclerView adapters. While making your Adapter related logic testable by
providing abstraction layer over its logic, it will make you forget all of the ViewType hassle all together.
Step 1. Add this in your root build.gradle
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
Step 2. Add the dependency
dependencies {
compile 'com.github.avito-tech:Konveyor:VERSION'
}
If you like to stay on the bleeding edge, or use certain commit as your dependency,
you can use the short commit hash or anyBranch-SNAPSHOT
as the version
<dependency>
<groupId>com.github.avito-tech</groupId>
<artifactId>Konveyor</artifactId>
<version>VERSION</version>
</dependency>
Konveyor introduces set of key abstractions to extract knowledge about ids and view types away
from RecyclerView.Adapter
, thus, making all of the associated logic easily extensible and testable.
Item is an interface that represents data associated with a certain ViewType
:
class Dog(override val id: Long) : Item
id — identifier, that RecyclerView.Adapter
will use in its methods.
ItemView is an abstraction over RecyclerView.ViewHolder
interface DogView : ItemView {
fun setName(name: String)
}
class DogViewHolder(view: View): BaseViewHolder(view), DogView {
private val name = view.findViewById(R.id.name) as TextView
override fun setName(name: String) {
this.name.text = name
}
}
onUnbind()
is called whenever RecyclerView.Adapter
calls onViewRecycled()
method for this ItemView.
You can override this method in case you need, for example, unsubscribe from listeners or release some resources associated with this ViewHolder
.
ItemPresenter connects Item
and its view. Essentially, your implementation of the interface should contain everything you would normally do in onBindViewHolder()
method of RecyclerView.Adapter
class DogPresenter: ItemPresenter<DogItemView, Dog> {
override fun bindView(view: DogView, item: Dog, position: Int) {
view.setName(item.name)
}
}
ItemBlueprint is a key entity that ties together Android world with our abstractions
class DogBlueprint(override val presenter: ItemPresenter<DogView, Dog>)
: ItemBlueprint<DogView, Dog> {
override val viewHolderProvider = ViewHolderBuilder.ViewHolderProvider(
layoutId = R.layout.dog_item,
creator = { _, view -> DogViewHolder(view) }
)
override fun isRelevantItem(item: Item): Boolean = item is Dog
}
RecyclerView.ViewHolder
Item
and its ItemBlueprint
.
Please mind, in the list of registered ItemBlueprint
s every check has to be unique.
If multiple registered ItemBlueprint
s respond true
to a given Item
, ViewTypeCollisionException
will be thrown.AdapterPresenter is an abstraction over RecyclerView.Adapter
, that we can easily use in our unit tests.
Current library provides default implementation for this interface - SimpleAdapterPresenter
, this will satisfy 99.9% of your needs, unless you need something exotic.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val recycler = view.findViewById(R.id.recycler) as RecyclerView
val binder = ItemBinder.Builder()
.registerItem(createDogBlueprint())
.registerItem(createCatBlueprint())
val adapterPresenter = SimpleAdapterPresenter(binder, binder)
recycler.adapter = SimpleRecyclerAdapter(adapterPresenter, binder)
}
In most cases SimpleRecyclerAdapter
, provided by this library will satisfy your needs.
This way you don't have to think about providing unique ViewType
s for your data, as ItemBinder
will handle this for you.
Philip Uvarov (philuvarov@gmail.com)
MIT