Litho: How to lazy load list items?

Created on 24 Nov 2017  路  4Comments  路  Source: facebook/litho

Version

// litho
implementation 'com.facebook.litho:litho-core:0.8.0'
implementation 'com.facebook.litho:litho-widget:0.8.0'
compileOnly 'com.facebook.litho:litho-annotations:0.8.0'

annotationProcessor 'com.facebook.litho:litho-processor:0.8.0'

// Sections
implementation 'com.facebook.litho:litho-sections-core:0.8.0'
implementation 'com.facebook.litho:litho-sections-widget:0.8.0'
compileOnly 'com.facebook.litho:litho-sections-annotations:0.8.0'

annotationProcessor 'com.facebook.litho:litho-sections-processor:0.8.0'

// SoLoader
implementation 'com.facebook.soloader:soloader:0.2.0'

Initially I load 15 items using DataDiffSection and a SingleComponentSection for progressBar at the end. Using onViewportChanged I trigger the data fetch to fetch the next 15 items.

But the problem is that already displayed list is getting replaced with the new list, instead of adding the new list to the end.

This is the code:
ListSectionSpec.java

```@GroupSectionSpec
public class ListSectionSpec {

@OnCreateInitialState
static void createInitialState(
final SectionContext c,
StateValue> feeds,
StateValue start,
StateValue count
) {
start.set(0);
count.set(15);
feeds.set(new DataService().getData(0, 15).feeds);
}

@OnCreateChildren
static Children onCreateChildren(
final SectionContext c,
@State List feeds,
@State int start,
@State int count
) {

return Children.create()
  .child(
    DataDiffSection.<Feed>create(c)
      .data(feeds)
      .renderEventHandler(ListSection.onRender(c))
      .build()
  )
  .child(
    SingleComponentSection.create(c)
      .component(
        Progress.create(c)
          .widthDip(40)
          .heightDip(40)
          .alignSelf(YogaAlign.CENTER)
          .build()
      )
      .build()
  )
  .build();

}

@OnCreateService
static DataService onCreateService(
final SectionContext c,
@State List feeds,
@State int start,
@State int count
) {
return new DataService();
}

@OnBindService
static void onBindService(final SectionContext c, final DataService service) {
service.registerLoadingEvent(ListSection.onDataLoaded(c));
}

@OnUnbindService
static void onUnbindService(final SectionContext c, final DataService service) {
service.unregisterLoadingEvent();
}

@OnRefresh
static void onRefresh(
SectionContext c,
DataService service,
@State List feeds,
@State int start,
@State int count
) {
service.refetch(0, 15);
}

@OnEvent(FeedModel.class)
static void onDataLoaded(final SectionContext c, @FromEvent List feeds) {
ListSection.updateData(c, feeds);
SectionLifecycle.dispatchLoadingEvent(c, false, LoadingState.SUCCEEDED, null);
}

@OnUpdateState
static void updateData(
final StateValue> feeds,
final StateValue start,
@Param List newFeeds
) {
if (start.get() == 0) {
feeds.set(newFeeds);
} else {
feeds.set(newFeeds);
}
}

@OnEvent(RenderEvent.class)
static RenderInfo onRender(final SectionContext c, @FromEvent Feed model) {
ComponentRenderInfo.Builder builder = ComponentRenderInfo.create();

builder.component(
  ListItem.create(c)
    .type(model.type)
    .bgColor(Color.WHITE)
    .title(model.data.title)
    .description(model.data.description)
    .imageRes(model.data.photos)
    .build()
);

return builder.build();

}

@OnUpdateState
static void updateStartParam(final StateValue start, @Param int newStart) {
start.set(newStart);
}

@OnViewportChanged
static void onViewportChanged(
SectionContext c,
int firstVisiblePosition,
int lastVisiblePosition,
int firstFullyVisibleIndex,
int lastFullyVisibleIndex,
int totalCount,
DataService service,
@State List feeds,
@State int start,
@State int count
) {
if (totalCount == feeds.size()) {
ListSection.updateStartParam(c, feeds.size());
service.fetch(feeds.size(), count);
}
}

}

Most helpful comment

It appears you're replacing the existing list in @State List<Feed> feeds with the newly fetched list in updateData() does your service return just the new 15 items or the new items plus the old ones?

If the former, changing your update data method to append the newly fetched items should work.

All 4 comments

It appears you're replacing the existing list in @State List<Feed> feeds with the newly fetched list in updateData() does your service return just the new 15 items or the new items plus the old ones?

If the former, changing your update data method to append the newly fetched items should work.

Oh got it! So I changed my else part like this and it works:

  else {
      List<Feed> allFeeds = new ArrayList<>();
      allFeeds.addAll(feeds.get());
      allFeeds.addAll(newFeeds);
      feeds.set(allFeeds);
    }

Is this correct or is there any better way?

Looks good! Only thing I'd suggest is using one of the non-default constructors for ArrayList since you already know how big the initial ArrayList will be.

Sure! Thanks @dsyang

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sockeqwe picture sockeqwe  路  5Comments

passy picture passy  路  3Comments

tpucci picture tpucci  路  4Comments

pavlospt picture pavlospt  路  5Comments

Drewbi picture Drewbi  路  3Comments