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
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
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
})
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
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!
}
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
-
Data < 100: Use
ForEach
directly, simple and efficient. -
Data > 100:
- Must use
LazyForEach + cachedCount
- For many network requests, add dynamic prefetch
- For complex list items, add
**@Reusable**
reuse
- Must use
-
Layout Principles:
- Use
RelativeContainer
/Grid
more - Nesting levels ≤ 8
- Use
-
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)