in litho-sections-widget/src/main/java/com/facebook/litho/sections/widget/RecyclerCollectionComponentSpec.java [273:398]
static void createInitialState(
final ComponentContext c,
StateValue<SnapHelper> snapHelper,
StateValue<SectionTree> sectionTree,
StateValue<RecyclerCollectionLoadEventsHandler> recyclerCollectionLoadEventsHandler,
StateValue<Binder<RecyclerView>> binder,
StateValue<LoadingState> loadingState,
StateValue<RecyclerCollectionEventsController> internalEventsController,
StateValue<LayoutInfo> layoutInfo,
@Prop Section section,
@Prop(optional = true) RecyclerConfiguration recyclerConfiguration,
@Prop(optional = true) @Nullable RecyclerCollectionEventsController eventsController,
@Prop(optional = true) boolean asyncPropUpdates,
@Prop(optional = true) boolean asyncStateUpdates,
// NB: This is a *workaround* for sections that use non-threadsafe models, e.g. models that
// may be updated from the main thread while background changesets would be calculated. It has
// negative performance implications since it forces all changesets to be calculated on the
// main thread!
@Prop(optional = true) boolean forceSyncStateUpdates,
// Caution: ignoreLoadingUpdates breaks loadingComponent/errorComponent/emptyComponent.
// It's intended to be a temporary workaround, not something you should use often.
@Prop(optional = true) boolean ignoreLoadingUpdates,
@Prop(optional = true) String sectionTreeTag,
@Prop(optional = true) boolean canMeasureRecycler,
// Don't use this. If false, off incremental mount for all subviews of this Recycler.
@Prop(optional = true) boolean incrementalMount,
@Prop(optional = true) @Nullable LithoStartupLogger startupLogger,
@Prop(optional = true) StickyHeaderControllerFactory stickyHeaderControllerFactory) {
RecyclerBinderConfiguration binderConfiguration =
recyclerConfiguration.getRecyclerBinderConfiguration();
final LayoutInfo newLayoutInfo = recyclerConfiguration.getLayoutInfo(c);
layoutInfo.set(newLayoutInfo);
RecyclerBinder.Builder recyclerBinderBuilder =
new RecyclerBinder.Builder()
.layoutInfo(newLayoutInfo)
.rangeRatio(binderConfiguration.getRangeRatio())
.layoutHandlerFactory(binderConfiguration.getLayoutHandlerFactory())
.wrapContent(binderConfiguration.isWrapContent())
.enableStableIds(binderConfiguration.getEnableStableIds())
.invalidStateLogParamsList(binderConfiguration.getInvalidStateLogParamsList())
.threadPoolConfig(binderConfiguration.getThreadPoolConfiguration())
.hscrollAsyncMode(binderConfiguration.getHScrollAsyncMode())
.isCircular(binderConfiguration.isCircular())
.hasDynamicItemHeight(binderConfiguration.hasDynamicItemHeight())
.incrementalMount(incrementalMount)
.stickyHeaderControllerFactory(stickyHeaderControllerFactory)
.componentsConfiguration(binderConfiguration.getComponentsConfiguration())
.canInterruptAndMoveLayoutsBetweenThreads(
binderConfiguration.moveLayoutsBetweenThreads())
.isReconciliationEnabled(binderConfiguration.isReconciliationEnabled())
.isLayoutDiffingEnabled(binderConfiguration.isLayoutDiffingEnabled())
.componentWarmer(binderConfiguration.getComponentWarmer())
.lithoViewFactory(binderConfiguration.getLithoViewFactory())
.errorEventHandler(binderConfiguration.getErrorEventHandler())
.startupLogger(startupLogger);
if (binderConfiguration.getEstimatedViewportCount()
!= RecyclerBinderConfiguration.Builder.UNSET) {
recyclerBinderBuilder.estimatedViewportCount(binderConfiguration.getEstimatedViewportCount());
}
RecyclerBinder recyclerBinder = recyclerBinderBuilder.build(c);
SectionBinderTarget targetBinder =
new SectionBinderTarget(recyclerBinder, binderConfiguration.getUseBackgroundChangeSets());
final SectionContext sectionContext = new SectionContext(c);
binder.set(targetBinder);
snapHelper.set(recyclerConfiguration.getSnapHelper());
final SectionTree sectionTreeInstance =
SectionTree.create(sectionContext, targetBinder)
.tag(
sectionTreeTag == null || sectionTreeTag.equals("")
? section.getSimpleName()
: sectionTreeTag)
.asyncPropUpdates(asyncPropUpdates)
.asyncStateUpdates(asyncStateUpdates)
.forceSyncStateUpdates(forceSyncStateUpdates)
.changeSetThreadHandler(binderConfiguration.getChangeSetThreadHandler())
.postToFrontOfQueueForFirstChangeset(
binderConfiguration.isPostToFrontOfQueueForFirstChangeset())
.build();
sectionTree.set(sectionTreeInstance);
final RecyclerCollectionEventsController internalEventsControllerInstance =
eventsController != null ? eventsController : new RecyclerCollectionEventsController();
internalEventsControllerInstance.setSectionTree(sectionTreeInstance);
internalEventsControllerInstance.setSnapMode(recyclerConfiguration.getSnapMode());
internalEventsController.set(internalEventsControllerInstance);
final RecyclerCollectionLoadEventsHandler recyclerCollectionLoadEventsHandlerInstance =
new RecyclerCollectionLoadEventsHandler(
c, internalEventsControllerInstance, ignoreLoadingUpdates);
recyclerCollectionLoadEventsHandler.set(recyclerCollectionLoadEventsHandlerInstance);
sectionTreeInstance.setLoadEventsHandler(recyclerCollectionLoadEventsHandlerInstance);
final ViewportInfo.ViewportChanged viewPortChanged =
new ViewportInfo.ViewportChanged() {
@Override
public void viewportChanged(
int firstVisibleIndex,
int lastVisibleIndex,
int firstFullyVisibleIndex,
int lastFullyVisibleIndex,
int state) {
sectionTreeInstance.viewPortChanged(
firstVisibleIndex,
lastVisibleIndex,
firstFullyVisibleIndex,
lastFullyVisibleIndex,
state);
}
};
targetBinder.setViewportChangedListener(viewPortChanged);
targetBinder.setCanMeasure(canMeasureRecycler);
if (ignoreLoadingUpdates) {
loadingState.set(LoadingState.LOADED);
} else {
loadingState.set(LoadingState.LOADING);
}
}