Search code examples
androidkotlinandroid-viewbindingepoxyepoxy-modelview

View binding with EpoxyModelWithHolder


I am using EpoxyModelWithHolder with multiple layouts in a single Epoxy model class. How can I do ViewBinding? Currently, I am using Kotlin-android-extensions. Below is my code

@EpoxyModelClass
abstract class ItemSampleEpoxyModel : EpoxyModelWithHolder() {

@EpoxyAttribute
var itemSampleShelf: ComponentFactoryLanderPagesHeroShelf.ComponentLanderPageHeroShelf.ItemLanderPageHeroShelf? =
    null

override fun getDefaultLayout() =
    when {
        itemSampleShelf?.heroStyle == "Project" -> {
            R.layout.item_project_sample
        }
        itemSampleShelf?.shelfItemType == "Course" -> {
            R.layout.item_course_sample
        }
        else -> {
            R.layout.item_sample
        }
    }

override fun bind(itemHolder: ItemSampleEpoxyHolder) {
    itemHolder.titleView.text = itemSampleShelf?.title
} }



class ItemSampleEpoxyHolder : EpoxyHolder() {


lateinit var titleView: AppCompatTextView

override fun bindView(itemView: View) {
    titleView = itemView.tv_title
}}

Solution

  • First add dependency of epoxy:

    def epoxyVersion = '4.6.3'
    implementation "com.airbnb.android:epoxy:$epoxyVersion"
    implementation "com.airbnb.android:epoxy-databinding:$epoxyVersion"
    kapt "com.airbnb.android:epoxy-processor:$epoxyVersion"
    

    After that we need to configure epoxy. In order to do this we need to make a package-info.java file inside the app module and write the below code.

    @EpoxyDataBindingPattern(rClass = R.class, layoutPrefix = "epoxy_item")
    interface Config {
    }
    

    Then we need to keep one thing in mind that whenever we are creating a layout it should be a data binding layout and its name should follow the value defined in the layoutPrefix variable in package-info for example in my case the layoutPrefix is epoxy_item so whenever I name a layout it starts with epoxy_item.

    Sample Layout: (Layout Name -> epoxy_item_loading)

    <?xml version="1.0" encoding="utf-8"?>
    
      <layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <data>
    
        <variable
            name="isVisible"
            type="Boolean" />
    
    
    </data>
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:isVisible="@{isVisible}">
    
        <ProgressBar
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="10dp"
            android:theme="@style/ProgressBlueTheme"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
     </layout>
    

    Now to add this layout to epoxy recycler view:

            epoxyRecycler.withModels {
                   loading {
                    id("progress layout")
                    isVisible(isLoading)// boolean variable
                }
            }
    

    That's all we need to do :)

    NOTE: Sometimes the auto generated classes for the layout is not generated in android studio, so in that case android studio will show the model as unrecognised and red line below it. In that case you need to rebuild the project. sometimes, clean and rebuild project.}