Skip to content

Basic Usage

Eli Hart edited this page Sep 24, 2017 · 13 revisions

There are two main components of Epoxy:

  1. The EpoxyModels that describe how your views should be displayed in the RecyclerView.
  2. The EpoxyController where the models are used to describe what items to show and with what data.

Creating Models

There are a few ways to create models, depending on whether you prefer to use custom views, databinding, or other approaches.

From Custom Views

You can easily generate an EpoxyModel from your custom views by using the @ModelView annotation on the class. Then, add a "prop" annotation on each setter method to mark it as a property for the model.

@ModelView(autoLayout = Size.MATCH_WIDTH_WRAP_HEIGHT)
public class HeaderView extends LinearLayout {

  ... // Initialization omitted

  @TextProp // Use this annotation for text.
  public void setTitle(CharSequence text) {
    titleView.setText(text);
  }

  @CallbackProp // Use this annotation for click listeners or other callbacks.
  public void clickListener(@Nullable OnClickListener listener) {
    setOnClickListener(listener
  }

  @ModelProp // Use this annotation for any other property type
  public void setBackgroundUrl(String url) {
    ...
  }
}

From DataBinding

If you use Android DataBinding you can simply set up your xml layouts like normal:

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="url"
            type="String" />

    </data>

    <Button
        android:layout_width="120dp"
        android:layout_height="40dp"
        android:imageUrl="@{url}" />
</layout>

Then, create a package-info.java class in the package you want the models generated and add an EpoxyDataBindingLayouts annotation to declare all of the databinding layouts that should be used to create models.

@EpoxyDataBindingLayouts({R.layout.photo, ... // other layouts })
package com.airbnb.epoxy.sample;

import com.airbnb.epoxy.EpoxyDataBindingLayouts;
import com.airbnb.epoxy.R;

Epoxy generates a model that includes all the variables for that layout.

Other ways

You can also create EpoxyModel's from Litho components, viewholders, or completely manually. See the wiki sidebar for more information on these approaches in depth.

Using your models in a controller

A controller defines what items should be shown in the RecyclerView, by adding the corresponding models in the desired order.

The controller's buildModels method declares the current view, and is called whenever the data backing the view changes. Epoxy tracks changes in the models and automatically binds and updates views.

As an example, our PhotoController shows a header, a list of photos, and a loader (if more photos are being loaded). The controller's setData(photos, loadingMore) method is called whenever photos are loaded, which triggers a call to buildModels so models representing the state of the new data can be built.

public class PhotoController extends Typed2EpoxyController<List<Photo>, Boolean> {
    @AutoModel HeaderModel_ headerModel;
    @AutoModel LoaderModel_ loaderModel;

    @Override
    protected void buildModels(List<Photo> photos, Boolean loadingMore) {
      headerModel
          .title("My Photos")
          .description("My album description!")
          .addTo(this);

      for (Photo photo : photos) {
        new PhotoModel()
           .id(photo.id())
           .url(photo.url())
           .addTo(this);
      }

      loaderModel
          .addIf(loadingMore, this);
    }
  }

Kotlin

Usage with Kotlin is even simpler! An extension function is generated for each model so we can write this:

class PhotoController : Typed2EpoxyController<List<Photo>, Boolean>() {

    override buildModels(photos: List<Photo>, loadingMore: Boolean) {
      headerModel {
          id("header")
          title("My Photos")
          description("My album description!")
     }

      photos.forEach {
         photo {
           .id(it.id())
           .url(it.url())
         }
      }

      if(loadingMore) loaderModel { id("loader") }
    }
  }

And that's it! The controller's declarative style makes it very easy to visualize what the RecyclerView will look like, even when many different view types or items are used. Epoxy handles everything else. If a view only partially changes, such as the description, only that new value is set on the view, so the system is very efficient

Epoxy handles much more than these basics, and is highly configurable. See the wiki for in depth documentation.