Mobile Development 13 min read

Optimizing Flutter List Performance: Element Reuse, Auto‑diff, Placeholder Widgets, Frame‑splitting Rendering, and Bidirectional Loading

This article examines the challenges of fluid list rendering in Flutter mobile apps and presents a series of performance optimizations—including element and RenderObject reuse, an auto‑diff algorithm, placeholder widgets, frame‑splitting rendering, pre‑loading, and bidirectional loading—along with functional extensions and real‑world results.

ByteDance Terminal Technology
ByteDance Terminal Technology
ByteDance Terminal Technology
Optimizing Flutter List Performance: Element Reuse, Auto‑diff, Placeholder Widgets, Frame‑splitting Rendering, and Bidirectional Loading

Background

In mobile development, scrollable lists are core business scenarios, but as complexity grows they often cause frame drops and white screens. The Flutter infra team collaborated with product teams to improve list smoothness and usability.

List Principle Overview

The list rendering pipeline consists of Viewport detecting the need for a new child, creating the ChildWidget and its Element, mounting the Element, creating and attaching a RenderObject, performing layout and paint, and finally unmounting and destroying elements that leave the cache.

Performance Optimizations

Element and RenderObject Reuse

ListView now reuses elements using a linear reuse algorithm, reducing the cost of destroying and recreating children when only their content changes. The solution wraps reused children with a KeepAlive‑like mechanism while avoiding full memory retention.

Auto‑diff

An implementation of Paul‑Heckel's Difference Algorithm automatically compares old and new data sequences, computing the minimal set of moves, updates, deletions, and insertions, thereby minimizing unnecessary element and RenderObject creation, mounting, and destruction.

Placeholder Widget

During rapid scrolling or scrollToTop(), placeholder children are used to delay rendering, caching size information and wrapping with a ConstraintBox to create a RelayoutBoundary, which reduces layout work when swapping placeholders for real content.

Frame‑splitting Rendering

A frame queue is maintained in the list's performLayout method, breaking layout work into tasks that are spread across frames, allowing partial layout to continue in subsequent frames and smoothing spikes in rendering time.

List Element Pre‑loading

By building and laying out upcoming children during idle frames, the list reduces the cost of creating new elements when the user scrolls, flattening the frame‑time curve.

Functional Extensions

Bidirectional Loading

Supports loading data both forward and backward (e.g., chat history), using hooks in SliverElement to control RenderObject loading when the list reaches the top or bottom.

jumpTo(int index)

Implemented by invoking setState twice: first to reset the scroll offset and partially load data, then to load the remaining data, ensuring performLayout runs for both steps.

scrollTo(int index)

Handles three cases: target child already in view, child previously laid out (cached size enables fast jump), and child beyond cache (fallback to a fuzzy transition animation followed by jumpTo).

Extended Lifecycle

Listens to mount events directly in performLayout to provide richer exposure callbacks with lower overhead compared to wrapping each child.

Online Results

The optimized list component has been deployed in several products (e.g., 大力家长, 小荷, Sharee). Enabling optimizations such as element reuse, frame‑splitting, and placeholder widgets yields more than a 3‑frame FPS improvement during scrolling.

Summary and Outlook

Flutter’s lightweight widget design enables declarative UI but limits fine‑grained control over view lifecycles, leading to frame drops in compute‑intensive scenarios like scrolling. The article presented several optimization techniques and functional extensions, and future work will address nested scroll views, gesture propagation, and other complex cases.

References

[0] https://github.com/flutter/flutter/issues/22393 [1] https://github.com/flutter/flutter/issues/21023 [2] https://dl.acm.org/doi/10.1145/359460.359467 [3] https://github.com/LianjiaTech/keframe [4] https://github.com/google/flutter.widgets/tree/master/packages/scrollable_positioned_list

About ByteDance Client Infrastructure Team

The ByteDance Client Infrastructure team is a global front‑end foundation engineering group responsible for performance, stability, and engineering efficiency across products such as Douyin, Toutiao, Xigua Video, Feishu, and more, covering mobile, web, and desktop platforms.

dartfluttermobilePerformanceoptimizationListView
ByteDance Terminal Technology
Written by

ByteDance Terminal Technology

Official account of ByteDance Terminal Technology, sharing technical insights and team updates.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.