Skip to content

View Binder

Peter Elliott edited this page May 14, 2021 · 1 revision

EpoxyViewBinder allows for EpoxyModels to be used outside of a recycler view. This is useful when inserting views of variable types into a layout or updating a view's data with an EpoxyModel.

Set up

View binders are part of a separate Epoxy module that you must add with

dependencies {
  implementation 'com.airbnb.android:epoxy-viewbinder:4.6.1' // Use latest epoxy version here
}

Usage

The recommended way to use view binders is to use the extension functions on an Activity/Fragment/ViewGroup. This uses an object that observes the Lifecycle of the Activity/Fragment/ViewGroup and will perform clean up when the lifecycle is destroyed. You must manually call LifecycleAwareEpoxyViewBinder.invalidate() for the model to be built and the view to be created/replaced in the your layout. This should also be called when the underlying data changes. The following is an example usage with an Activity.

  1. Add an EpoxyViewStub to your XML layout (can also be done programmatically, just need know the resource ID):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.airbnb.epoxy.EpoxyViewStub
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
   
    <!-- Other views as needed -->
</LinearLayout>
  1. Create a member variable for the view binder:
class MainActivity : AppCompatActivity() {

    private var headerTitle: String = "Default"

    private val viewBinder by epoxyView(
        viewId = R.id.header,
        modelProvider = {
            header {
                id("header")
                title(headerTitle)
                description("My album description!")
            }
        }
    )
    
    ...
}
  1. Call invalidate() when data has been updated:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity)
    headerTitle = "My photos" // Hard-coded for clarity
        
    // Call invalidate to create the model and replace the 
    // stub view with the model's view. This will create 
    // the model with the latest `headerTitle` value.
    viewBinder.invalidate()
}

Usage with Mavericks

If using Mavericks and backing the view binder with state values, you can populate the model like so:

private val viewBinder by epoxyView(
    viewId = R.id.header,
    modelProvider = {
        buildHeader()
    }
)

private fun ModelCollector.buildHeader() = withState(viewModel) { state ->
    header {
      id("header")
      title(state.headerTitle)
      description(state.description)
    }
}

Then in the MavericksView.invalidate() method invalidate the view binder:

override fun invalidate() {
    viewBinder.invalidate()
}

Visibility Events

Visibility events are supported if using the supplied extension functions that create a LifecycleAwareEpoxyViewBinder. Simply pass useVisibilityTracking = true when creating the object. If you're not using these extension functions then you'll need to manually attach and detach a EpoxyViewBinderVisibilityTracker on the view as needed.