DEV Community

陈杨
陈杨

Posted on

Treasure Case Sharing of HarmonyOS 5 Development — Analysis of Long List Performance Optimization

HarmonyOS Long List Performance Optimization Revealed! Say Goodbye to Lag, with Practical Code Analysis!

Hello everyone~ While browsing the HarmonyOS developer documentation today, I discovered a treasure case of performance optimization! The official team quietly released a complete solution for long list lag, and the actual results are amazing! I've compiled the key points overnight, and will guide you step by step to optimize HarmonyOS list performance, with full code analysis! 👇


🌟 Why Do Long Lists Lag? Let's See the Pain Points First!

When the list data exceeds 1000 items, the traditional ForEach loading method will cause:

  • Memory Soars (10,000 items take up 560MB of memory!)
  • First screen load takes 5+ seconds, scrolling drops frames like crazy (frame drop rate 58%)
  • Fast scrolling shows white blocks, even causing the app to crash!

Core Optimization Goals: Reduce TTFD (Time to First Draw), decrease frame drop rate, and compress memory usage!


🚀 Five Optimization Techniques + Practical Code

✅ 1. Lazy Loading (LazyForEach) — First Screen Acceleration Tool

Principle: Only load the data currently visible on the screen (e.g., 6 items), instead of loading all 10,000 items at once!

// Traditional ForEach (loads all at once) → Disable!
ForEach(this.articleList, (item) => {
  ListItem() { ArticleCardView(item) }
})

// ✅ Use LazyForEach (load on demand)
LazyForEach(this.data, (item: LearningResource) => {
  ListItem() { ArticleCardView(item) }
}, (item) => item.id) // Use id as unique identifier
Enter fullscreen mode Exit fullscreen mode

Performance Comparison:

Data Volume ForEach First Screen Time LazyForEach First Screen Time
10,000 items 5841ms 1707ms (70% faster)

💡 Applicable Scenario: Must use when data > 100 items! For less than 100, ForEach is simpler.


✅ 2. Cache List Items (cachedCount) — Smoother Scrolling

Principle: Preload off-screen data to solve white block issues during fast scrolling.

List() {
  LazyForEach(this.data, ...)
}
.cachedCount(3) // ✅ Key setting: cache 3 items off-screen
Enter fullscreen mode Exit fullscreen mode

Golden Rule for Cache Count:

  • One screen shows 6 items → set cachedCount=3 (cache half off-screen)
  • If the list contains images/videos → appropriately increase cache (e.g., cachedCount=6)
  • Actual Results:
    • No cache: frame drop rate 6.6%
    • Cache 3 items: frame drop rate drops to 3.7%!

✅ 3. Dynamic Prefetching (Prefetcher) — Savior for Poor Networks

Principle: When the network is poor, intelligently prefetch images and other resources to completely eliminate white blocks!

// Step1: Implement prefetch interface
class DataSourcePrefetching implements IDataSourcePrefetching {
  async prefetch(index: number) {
    // Write network request logic here (example: prefetch image)
    const response = await session.fetch(request);
    item.cachedImage = await this.cache(response.body); 
  }
}

// Step2: Bind prefetcher in List
private readonly prefetcher = new BasicPrefetcher(this.dataSource);

List()
  .onScrollIndex((start, end) => {
    this.prefetcher.visibleAreaChanged(start, end) // ✅ Trigger prefetch on scroll
  })
Enter fullscreen mode Exit fullscreen mode

Results:

Scheme First Screen Time White Blocks on Scroll CPU Usage
cachedCount=5 530ms Many 3.96%
Dynamic Prefetch 545ms 0 white blocks 4.12%

✅ 4. Component Reuse (@Reusable) — Reuse DOM to Reduce Memory

Principle: List items are not destroyed after leaving the screen, but put into a cache pool for reuse!

// ✅ Step1: Decorate component with @Reusable
@Reusable 
@Component
struct ReusableArticleCardView {
  aboutToReuse(params: Record<string, Object>) {
    // Update data on reuse (10x faster than recreating!)
    this.onLiked = params.onLiked as () => void;
  }
  build() { ... }
}

// ✅ Step2: Mark reuseId in LazyForEach
ListItem() {
  ReusableArticleCardView(...)
}
.reuseId('article') // Reuse components of the same type
Enter fullscreen mode Exit fullscreen mode

Performance Boost:

  • Component creation time: 10.2ms → 0.97ms
  • 10,000-item list frame drop rate: 3.7% → 0%

✅ 5. Layout Optimization — Reduce Nesting Levels

Principle: Flatten layouts to reduce view hierarchy and speed up rendering!

// ❌ Wrong Example: 5-level nesting (poor performance)
Column() {
  Row() {
    Column() {
      Text(...)
      Row() { ... } // Deeper nesting
    }
  }
}

// ✅ Correct Approach: Use RelativeContainer instead
RelativeContainer() { 
  Text().alignRules({ top: { anchor: "__container__", align: VerticalAlign.Top } })
  Image().alignRules({ centerX: { anchor: "__container__", align: HorizontalAlign.Center } })
  // All components are on the same level!
}
Enter fullscreen mode Exit fullscreen mode

Results:

Layout Levels Memory Usage Frame Drop Rate
5 levels 80.1MB 0%
25 levels 153.7MB 2.3%

Key Point: Keep levels within 5~8; over-optimization makes maintenance difficult!


📊 Ultimate Performance Comparison

After optimization, 10,000 items:

Metric Before Optimization After Optimization Improvement
First Screen Time 5841ms 1339ms 77%
Frame Drop Rate 58.2% 0% Completely smooth
Memory Usage 560.1MB 78.4MB 86%

💎 Summary & Pitfall Guide

  1. Data < 100: Use ForEach directly, simple and efficient.
  2. Data > 100:
    • Must use LazyForEach + cachedCount
    • For many network requests, add dynamic prefetch
    • For complex list items, add **@Reusable** reuse
  3. Layout Principles:
    • Use RelativeContainer/Grid more
    • Nesting levels ≤ 8
  4. Performance Monitoring Tools:
    • Use DevEco Studio's Profiler to check TTFD/memory/frame drop rate

That's all for this sharing~ HarmonyOS's optimization solutions are really practical! If you encounter performance issues during development, be sure to check the official documentation's "App Quality" section, there are many hidden gems! If you have other questions, feel free to discuss in the comments~ ✨

Keep Coding, let your HarmonyOS app fly! 🚀

Top comments (0)