Sections work best when combined with the rendering optimizations that Litho Components offer. However, the API also provides support for rendering with Views instead of Components. This makes the transition to Sections easier and you can still take advantage of the performance benefits regardless of your product’s UI using traditional Views, Litho Components or a mix of the two.

View support is only offered by DataDiffSection at the moment. Let’s have another look at the DataDiffSection example to recap how you declare what the framework should render for a certain item.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@GroupSectionSpec
class MyGroupSection {

  @OnCreateChildren
  Children onCreateChildren(
      SectionContext c,
      @Prop ImmutableList<MyModel> dataModel) {
      return Children.create()
          .child(DataDiffSection.create(c)
              .data(dataModel)
              .renderEventHandler(MyGroupSection.onRenderEdge(c)))
          .build();
    }

  @OnEvent(RenderEvent.class)
  RenderInfo onRenderEdge(
      SectionContext c,
      @FromEvent MyModel model) {
      return ComponentRenderInfo.create(c)
          .component(MyModelItemComponent.create(c).item(model).build())
          .build();
  }
}

When an item needs to be rendered on screen, the framework dispatches a RenderEvent and it calls the event handler passed as prop to the DataDiffSection to create a RenderInfo for that item. RenderInfo holds information that allows the framework to understand how a certain item should be rendered.

RenderInfo has two implementations: ComponentRenderInfo and ViewRenderInfo.

We’ve seen in the previous example how to use ComponentRenderInfo to declare how an item should be rendered using Litho Components. If you want to render items with Views instead, all you have to do is return a ViewRenderInfo instance from the RenderEvent handler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@GroupSectionSpec
class MyGroupSection {

  @OnCreateChildren
  Children onCreateChildren(
      SectionContext c,
      @Prop ImmutableList<MyModel> dataModel) {
      return Children.create()
          .child(DataDiffSection.create(c)
              .data(dataModel)
              .renderEventHandler(MyGroupSection.onRenderEdge(c)))
          .build();
    }

  @OnEvent(RenderEvent.class)
  RenderInfo onRenderEdge(
      SectionContext c,
      @FromEvent MyModel model,
      @FromEvent int index) {
      return ViewRenderInfo.create(c)
          .viewCreator(
              new ViewCreator<MyView>() {
                  @Override
                  public View createView(Context c) {
                      // this call is equivalent to onCreateViewHolder()
                      return new MyView(c);
                  }
               })
          .viewBinder(
              new SimpleViewBinder<MyView>() {
                  @Override
                  public void bind(MyView view) {
                    // this call is equivalent to onBindViewHolder()
                  }
              })
          .build();
  }
}

ViewRenderInfo has two mandatory props that need to be passed to it: a ViewCreator and a ViewBinder.

ViewCreator and ViewBinder are the logical equivalent of onCreateViewHolder and onBindViewHolder methods of the RecyclerView.Adapter.

Views created by the same ViewCreator will be recycled. You can use the model or the index to decide amongst multiple view types and return the appropriate View from ViewCreator#createView().

The framework provides a no-op implementation of ViewBinder, called SimpleViewBinder, that you can use if only need to implement one of the ViewBinder methods, typically bind(View).

Mixing Components and Views

If your Section needs to render items partly with Litho Components, partly with Views, you can do that by returning the appropriate RenderInfo implementation from the RenderEvent handler. Here’s how you could do that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@GroupSectionSpec
class MyGroupSection {

  @OnCreateChildren
  Children onCreateChildren(
      SectionContext c,
      @Prop ImmutableList<MyModel> dataModel) {
      return Children.create()
          .child(DataDiffSection.create(c)
              .data(dataModel)
              .renderEventHandler(MyGroupSection.onRenderEdge(c)))
          .build();
    }

  @OnEvent(RenderEvent.class)
  RenderInfo onRenderEdge(
      SectionContext c,
      @FromEvent MyModel model) {
      if (model.canRenderWithComponent()) {
        return ComponentRenderInfo.create(c)
            .component(MyModelItemComponent.create(c).item(model).build())
            .build();
      }

      return ViewRenderInfo.create(c)
               .viewCreator(
                   new ViewCreator<MyView>() {
                       @Override
                       public View createView(Context c) {
                           // this call is equivalent to onCreateViewHolder()
                           return new MyView(c);
                       }
                    })
               .viewBinder(
                   new SimpleViewBinder<MyView>() {
                       @Override
                       public void bind(MyView view) {
                         // this call is equivalent to onBindViewHolder()
                       }
                   })
               .build();
  }
}

Edit on GitHub