@musashishao/agent-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/.agent/.shared/ui-ux-pro-max/scripts/search.py +76 -0
- package/.agent/ARCHITECTURE.md +225 -0
- package/.agent/CONTEXT.md +229 -0
- package/.agent/FEATURE_ROADMAP.md +435 -0
- package/.agent/PROMPT_TEMPLATES.md +261 -0
- package/.agent/agents/backend-specialist.md +263 -0
- package/.agent/agents/database-architect.md +226 -0
- package/.agent/agents/debugger.md +225 -0
- package/.agent/agents/devops-engineer.md +242 -0
- package/.agent/agents/documentation-writer.md +104 -0
- package/.agent/agents/explorer-agent.md +73 -0
- package/.agent/agents/frontend-specialist.md +556 -0
- package/.agent/agents/game-developer.md +162 -0
- package/.agent/agents/mobile-developer.md +377 -0
- package/.agent/agents/orchestrator.md +416 -0
- package/.agent/agents/penetration-tester.md +188 -0
- package/.agent/agents/performance-optimizer.md +187 -0
- package/.agent/agents/project-planner.md +403 -0
- package/.agent/agents/security-auditor.md +170 -0
- package/.agent/agents/seo-specialist.md +111 -0
- package/.agent/agents/test-engineer.md +158 -0
- package/.agent/rules/GEMINI.md +251 -0
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/bash-linux/SKILL.md +199 -0
- package/.agent/skills/behavioral-modes/SKILL.md +242 -0
- package/.agent/skills/brainstorming/SKILL.md +163 -0
- package/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/code-review-checklist/SKILL.md +109 -0
- package/.agent/skills/database-design/SKILL.md +52 -0
- package/.agent/skills/database-design/database-selection.md +43 -0
- package/.agent/skills/database-design/indexing.md +39 -0
- package/.agent/skills/database-design/migrations.md +48 -0
- package/.agent/skills/database-design/optimization.md +36 -0
- package/.agent/skills/database-design/orm-selection.md +30 -0
- package/.agent/skills/database-design/schema-design.md +56 -0
- package/.agent/skills/database-design/scripts/schema_validator.py +172 -0
- package/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/docker-expert/SKILL.md +409 -0
- package/.agent/skills/documentation-templates/SKILL.md +194 -0
- package/.agent/skills/frontend-design/SKILL.md +396 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +541 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/game-development/2d-games/SKILL.md +119 -0
- package/.agent/skills/game-development/3d-games/SKILL.md +135 -0
- package/.agent/skills/game-development/SKILL.md +167 -0
- package/.agent/skills/game-development/game-art/SKILL.md +185 -0
- package/.agent/skills/game-development/game-audio/SKILL.md +190 -0
- package/.agent/skills/game-development/game-design/SKILL.md +129 -0
- package/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
- package/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
- package/.agent/skills/game-development/pc-games/SKILL.md +144 -0
- package/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
- package/.agent/skills/game-development/web-games/SKILL.md +150 -0
- package/.agent/skills/geo-fundamentals/SKILL.md +156 -0
- package/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/lint-and-validate/SKILL.md +45 -0
- package/.agent/skills/lint-and-validate/scripts/lint_runner.py +172 -0
- package/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
- package/.agent/skills/mcp-builder/SKILL.md +176 -0
- package/.agent/skills/mobile-design/SKILL.md +394 -0
- package/.agent/skills/mobile-design/decision-trees.md +516 -0
- package/.agent/skills/mobile-design/mobile-backend.md +491 -0
- package/.agent/skills/mobile-design/mobile-color-system.md +420 -0
- package/.agent/skills/mobile-design/mobile-debugging.md +122 -0
- package/.agent/skills/mobile-design/mobile-design-thinking.md +357 -0
- package/.agent/skills/mobile-design/mobile-navigation.md +458 -0
- package/.agent/skills/mobile-design/mobile-performance.md +767 -0
- package/.agent/skills/mobile-design/mobile-testing.md +356 -0
- package/.agent/skills/mobile-design/mobile-typography.md +433 -0
- package/.agent/skills/mobile-design/platform-android.md +666 -0
- package/.agent/skills/mobile-design/platform-ios.md +561 -0
- package/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
- package/.agent/skills/mobile-design/touch-psychology.md +537 -0
- package/.agent/skills/nestjs-expert/SKILL.md +552 -0
- package/.agent/skills/nextjs-best-practices/SKILL.md +203 -0
- package/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
- package/.agent/skills/parallel-agents/SKILL.md +175 -0
- package/.agent/skills/performance-profiling/SKILL.md +143 -0
- package/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/.agent/skills/plan-writing/SKILL.md +152 -0
- package/.agent/skills/powershell-windows/SKILL.md +167 -0
- package/.agent/skills/prisma-expert/SKILL.md +355 -0
- package/.agent/skills/python-patterns/SKILL.md +441 -0
- package/.agent/skills/react-patterns/SKILL.md +198 -0
- package/.agent/skills/red-team-tactics/SKILL.md +199 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +129 -0
- package/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/.agent/skills/server-management/SKILL.md +161 -0
- package/.agent/skills/systematic-debugging/SKILL.md +109 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +269 -0
- package/.agent/skills/tdd-workflow/SKILL.md +149 -0
- package/.agent/skills/testing-patterns/SKILL.md +178 -0
- package/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/.agent/skills/typescript-expert/SKILL.md +429 -0
- package/.agent/skills/typescript-expert/references/tsconfig-strict.json +92 -0
- package/.agent/skills/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/.agent/skills/typescript-expert/references/utility-types.ts +335 -0
- package/.agent/skills/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +351 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
- package/.agent/skills/vulnerability-scanner/checklists.md +121 -0
- package/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/.agent/skills/webapp-testing/SKILL.md +187 -0
- package/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +80 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +231 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/bin/cli.js +235 -0
- package/index.js +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,767 @@
|
|
|
1
|
+
# Mobile Performance Reference
|
|
2
|
+
|
|
3
|
+
> Deep dive into React Native and Flutter performance optimization, 60fps animations, memory management, and battery considerations.
|
|
4
|
+
> **This file covers the #1 area where AI-generated code FAILS.**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. The Mobile Performance Mindset
|
|
9
|
+
|
|
10
|
+
### Why Mobile Performance is Different
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
DESKTOP: MOBILE:
|
|
14
|
+
├── Unlimited power ├── Battery matters
|
|
15
|
+
├── Abundant RAM ├── RAM is shared, limited
|
|
16
|
+
├── Stable network ├── Network is unreliable
|
|
17
|
+
├── CPU always available ├── CPU throttles when hot
|
|
18
|
+
└── User expects fast anyway └── User expects INSTANT
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Performance Budget Concept
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Every frame must complete in:
|
|
25
|
+
├── 60fps → 16.67ms per frame
|
|
26
|
+
├── 120fps (ProMotion) → 8.33ms per frame
|
|
27
|
+
|
|
28
|
+
If your code takes longer:
|
|
29
|
+
├── Frame drops → Janky scroll/animation
|
|
30
|
+
├── User perceives as "slow" or "broken"
|
|
31
|
+
└── They WILL uninstall your app
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. React Native Performance
|
|
37
|
+
|
|
38
|
+
### 🚫 The #1 AI Mistake: ScrollView for Lists
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
// ❌ NEVER DO THIS - AI's favorite mistake
|
|
42
|
+
<ScrollView>
|
|
43
|
+
{items.map(item => (
|
|
44
|
+
<ItemComponent key={item.id} item={item} />
|
|
45
|
+
))}
|
|
46
|
+
</ScrollView>
|
|
47
|
+
|
|
48
|
+
// Why it's catastrophic:
|
|
49
|
+
// ├── Renders ALL items immediately (1000 items = 1000 renders)
|
|
50
|
+
// ├── Memory explodes
|
|
51
|
+
// ├── Initial render takes seconds
|
|
52
|
+
// └── Scroll becomes janky
|
|
53
|
+
|
|
54
|
+
// ✅ ALWAYS USE FlatList
|
|
55
|
+
<FlatList
|
|
56
|
+
data={items}
|
|
57
|
+
renderItem={renderItem}
|
|
58
|
+
keyExtractor={item => item.id}
|
|
59
|
+
/>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### FlatList Optimization Checklist
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// ✅ CORRECT: All optimizations applied
|
|
66
|
+
|
|
67
|
+
// 1. Memoize the item component
|
|
68
|
+
const ListItem = React.memo(({ item }: { item: Item }) => {
|
|
69
|
+
return (
|
|
70
|
+
<Pressable style={styles.item}>
|
|
71
|
+
<Text>{item.title}</Text>
|
|
72
|
+
</Pressable>
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 2. Memoize renderItem with useCallback
|
|
77
|
+
const renderItem = useCallback(
|
|
78
|
+
({ item }: { item: Item }) => <ListItem item={item} />,
|
|
79
|
+
[] // Empty deps = never recreated
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// 3. Stable keyExtractor (NEVER use index!)
|
|
83
|
+
const keyExtractor = useCallback((item: Item) => item.id, []);
|
|
84
|
+
|
|
85
|
+
// 4. Provide getItemLayout for fixed-height items
|
|
86
|
+
const getItemLayout = useCallback(
|
|
87
|
+
(data: Item[] | null, index: number) => ({
|
|
88
|
+
length: ITEM_HEIGHT, // Fixed height
|
|
89
|
+
offset: ITEM_HEIGHT * index,
|
|
90
|
+
index,
|
|
91
|
+
}),
|
|
92
|
+
[]
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// 5. Apply to FlatList
|
|
96
|
+
<FlatList
|
|
97
|
+
data={items}
|
|
98
|
+
renderItem={renderItem}
|
|
99
|
+
keyExtractor={keyExtractor}
|
|
100
|
+
getItemLayout={getItemLayout}
|
|
101
|
+
// Performance props
|
|
102
|
+
removeClippedSubviews={true} // Android: detach off-screen
|
|
103
|
+
maxToRenderPerBatch={10} // Items per batch
|
|
104
|
+
windowSize={5} // Render window (5 = 2 screens each side)
|
|
105
|
+
initialNumToRender={10} // Initial items
|
|
106
|
+
updateCellsBatchingPeriod={50} // Batching delay
|
|
107
|
+
/>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Why Each Optimization Matters
|
|
111
|
+
|
|
112
|
+
| Optimization | What It Prevents | Impact |
|
|
113
|
+
|--------------|------------------|--------|
|
|
114
|
+
| `React.memo` | Re-render on parent change | 🔴 Critical |
|
|
115
|
+
| `useCallback renderItem` | New function every render | 🔴 Critical |
|
|
116
|
+
| Stable `keyExtractor` | Wrong item recycling | 🔴 Critical |
|
|
117
|
+
| `getItemLayout` | Async layout calculation | 🟡 High |
|
|
118
|
+
| `removeClippedSubviews` | Memory from off-screen | 🟡 High |
|
|
119
|
+
| `maxToRenderPerBatch` | Blocking main thread | 🟢 Medium |
|
|
120
|
+
| `windowSize` | Memory usage | 🟢 Medium |
|
|
121
|
+
|
|
122
|
+
### FlashList: The Better Option
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// Consider FlashList for better performance
|
|
126
|
+
import { FlashList } from "@shopify/flash-list";
|
|
127
|
+
|
|
128
|
+
<FlashList
|
|
129
|
+
data={items}
|
|
130
|
+
renderItem={renderItem}
|
|
131
|
+
estimatedItemSize={ITEM_HEIGHT}
|
|
132
|
+
keyExtractor={keyExtractor}
|
|
133
|
+
/>
|
|
134
|
+
|
|
135
|
+
// Benefits over FlatList:
|
|
136
|
+
// ├── Faster recycling
|
|
137
|
+
// ├── Better memory management
|
|
138
|
+
// ├── Simpler API
|
|
139
|
+
// └── Fewer optimization props needed
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Animation Performance
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// ❌ JS-driven animation (blocks JS thread)
|
|
146
|
+
Animated.timing(value, {
|
|
147
|
+
toValue: 1,
|
|
148
|
+
duration: 300,
|
|
149
|
+
useNativeDriver: false, // BAD!
|
|
150
|
+
}).start();
|
|
151
|
+
|
|
152
|
+
// ✅ Native-driver animation (runs on UI thread)
|
|
153
|
+
Animated.timing(value, {
|
|
154
|
+
toValue: 1,
|
|
155
|
+
duration: 300,
|
|
156
|
+
useNativeDriver: true, // GOOD!
|
|
157
|
+
}).start();
|
|
158
|
+
|
|
159
|
+
// Native driver supports ONLY:
|
|
160
|
+
// ├── transform (translate, scale, rotate)
|
|
161
|
+
// └── opacity
|
|
162
|
+
//
|
|
163
|
+
// Does NOT support:
|
|
164
|
+
// ├── width, height
|
|
165
|
+
// ├── backgroundColor
|
|
166
|
+
// ├── borderRadius changes
|
|
167
|
+
// └── margin, padding
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Reanimated for Complex Animations
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
// For animations native driver can't handle, use Reanimated 3
|
|
174
|
+
|
|
175
|
+
import Animated, {
|
|
176
|
+
useSharedValue,
|
|
177
|
+
useAnimatedStyle,
|
|
178
|
+
withSpring,
|
|
179
|
+
} from 'react-native-reanimated';
|
|
180
|
+
|
|
181
|
+
const Component = () => {
|
|
182
|
+
const offset = useSharedValue(0);
|
|
183
|
+
|
|
184
|
+
const animatedStyles = useAnimatedStyle(() => ({
|
|
185
|
+
transform: [{ translateX: withSpring(offset.value) }],
|
|
186
|
+
}));
|
|
187
|
+
|
|
188
|
+
return <Animated.View style={animatedStyles} />;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Benefits:
|
|
192
|
+
// ├── Runs on UI thread (60fps guaranteed)
|
|
193
|
+
// ├── Can animate any property
|
|
194
|
+
// ├── Gesture-driven animations
|
|
195
|
+
// └── Worklets for complex logic
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Memory Leak Prevention
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
// ❌ Memory leak: uncleared interval
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
const interval = setInterval(() => {
|
|
204
|
+
fetchData();
|
|
205
|
+
}, 5000);
|
|
206
|
+
// Missing cleanup!
|
|
207
|
+
}, []);
|
|
208
|
+
|
|
209
|
+
// ✅ Proper cleanup
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
const interval = setInterval(() => {
|
|
212
|
+
fetchData();
|
|
213
|
+
}, 5000);
|
|
214
|
+
|
|
215
|
+
return () => clearInterval(interval); // CLEANUP!
|
|
216
|
+
}, []);
|
|
217
|
+
|
|
218
|
+
// Common memory leak sources:
|
|
219
|
+
// ├── Timers (setInterval, setTimeout)
|
|
220
|
+
// ├── Event listeners
|
|
221
|
+
// ├── Subscriptions (WebSocket, PubSub)
|
|
222
|
+
// ├── Async operations that update state after unmount
|
|
223
|
+
// └── Image caching without limits
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### React Native Performance Checklist
|
|
227
|
+
|
|
228
|
+
```markdown
|
|
229
|
+
## Before Every List
|
|
230
|
+
- [ ] Using FlatList or FlashList (NOT ScrollView)
|
|
231
|
+
- [ ] renderItem is useCallback memoized
|
|
232
|
+
- [ ] List items are React.memo wrapped
|
|
233
|
+
- [ ] keyExtractor uses stable ID (NOT index)
|
|
234
|
+
- [ ] getItemLayout provided (if fixed height)
|
|
235
|
+
|
|
236
|
+
## Before Every Animation
|
|
237
|
+
- [ ] useNativeDriver: true (if possible)
|
|
238
|
+
- [ ] Using Reanimated for complex animations
|
|
239
|
+
- [ ] Only animating transform/opacity
|
|
240
|
+
- [ ] Tested on low-end Android device
|
|
241
|
+
|
|
242
|
+
## Before Any Release
|
|
243
|
+
- [ ] console.log statements removed
|
|
244
|
+
- [ ] Cleanup functions in all useEffects
|
|
245
|
+
- [ ] No memory leaks (test with profiler)
|
|
246
|
+
- [ ] Tested in release build (not dev)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 3. Flutter Performance
|
|
252
|
+
|
|
253
|
+
### 🚫 The #1 AI Mistake: setState Overuse
|
|
254
|
+
|
|
255
|
+
```dart
|
|
256
|
+
// ❌ WRONG: setState rebuilds ENTIRE widget tree
|
|
257
|
+
class BadCounter extends StatefulWidget {
|
|
258
|
+
@override
|
|
259
|
+
State<BadCounter> createState() => _BadCounterState();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
class _BadCounterState extends State<BadCounter> {
|
|
263
|
+
int _counter = 0;
|
|
264
|
+
|
|
265
|
+
void _increment() {
|
|
266
|
+
setState(() {
|
|
267
|
+
_counter++; // This rebuilds EVERYTHING below!
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@override
|
|
272
|
+
Widget build(BuildContext context) {
|
|
273
|
+
return Column(
|
|
274
|
+
children: [
|
|
275
|
+
Text('Counter: $_counter'),
|
|
276
|
+
ExpensiveWidget(), // Rebuilds unnecessarily!
|
|
277
|
+
AnotherExpensiveWidget(), // Rebuilds unnecessarily!
|
|
278
|
+
],
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### The `const` Constructor Revolution
|
|
285
|
+
|
|
286
|
+
```dart
|
|
287
|
+
// ✅ CORRECT: const prevents rebuilds
|
|
288
|
+
|
|
289
|
+
class GoodCounter extends StatefulWidget {
|
|
290
|
+
const GoodCounter({super.key}); // CONST constructor!
|
|
291
|
+
|
|
292
|
+
@override
|
|
293
|
+
State<GoodCounter> createState() => _GoodCounterState();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
class _GoodCounterState extends State<GoodCounter> {
|
|
297
|
+
int _counter = 0;
|
|
298
|
+
|
|
299
|
+
@override
|
|
300
|
+
Widget build(BuildContext context) {
|
|
301
|
+
return Column(
|
|
302
|
+
children: [
|
|
303
|
+
Text('Counter: $_counter'),
|
|
304
|
+
const ExpensiveWidget(), // Won't rebuild!
|
|
305
|
+
const AnotherExpensiveWidget(), // Won't rebuild!
|
|
306
|
+
],
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// RULE: Add `const` to EVERY widget that doesn't depend on state
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Targeted State Management
|
|
315
|
+
|
|
316
|
+
```dart
|
|
317
|
+
// ❌ setState rebuilds whole tree
|
|
318
|
+
setState(() => _value = newValue);
|
|
319
|
+
|
|
320
|
+
// ✅ ValueListenableBuilder: surgical rebuilds
|
|
321
|
+
class TargetedState extends StatelessWidget {
|
|
322
|
+
final ValueNotifier<int> counter = ValueNotifier(0);
|
|
323
|
+
|
|
324
|
+
@override
|
|
325
|
+
Widget build(BuildContext context) {
|
|
326
|
+
return Column(
|
|
327
|
+
children: [
|
|
328
|
+
// Only this rebuilds when counter changes
|
|
329
|
+
ValueListenableBuilder<int>(
|
|
330
|
+
valueListenable: counter,
|
|
331
|
+
builder: (context, value, child) => Text('$value'),
|
|
332
|
+
child: const Icon(Icons.star), // Won't rebuild!
|
|
333
|
+
),
|
|
334
|
+
const ExpensiveWidget(), // Never rebuilds
|
|
335
|
+
],
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Riverpod/Provider Best Practices
|
|
342
|
+
|
|
343
|
+
```dart
|
|
344
|
+
// ❌ WRONG: Reading entire provider in build
|
|
345
|
+
Widget build(BuildContext context) {
|
|
346
|
+
final state = ref.watch(myProvider); // Rebuilds on ANY change
|
|
347
|
+
return Text(state.name);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// ✅ CORRECT: Select only what you need
|
|
351
|
+
Widget build(BuildContext context) {
|
|
352
|
+
final name = ref.watch(myProvider.select((s) => s.name));
|
|
353
|
+
return Text(name); // Only rebuilds when name changes
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### ListView Optimization
|
|
358
|
+
|
|
359
|
+
```dart
|
|
360
|
+
// ❌ WRONG: ListView without builder (renders all)
|
|
361
|
+
ListView(
|
|
362
|
+
children: items.map((item) => ItemWidget(item)).toList(),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
// ✅ CORRECT: ListView.builder (lazy rendering)
|
|
366
|
+
ListView.builder(
|
|
367
|
+
itemCount: items.length,
|
|
368
|
+
itemBuilder: (context, index) => ItemWidget(items[index]),
|
|
369
|
+
// Additional optimizations:
|
|
370
|
+
itemExtent: 56, // Fixed height = faster layout
|
|
371
|
+
cacheExtent: 100, // Pre-render distance
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
// ✅ EVEN BETTER: ListView.separated for dividers
|
|
375
|
+
ListView.separated(
|
|
376
|
+
itemCount: items.length,
|
|
377
|
+
itemBuilder: (context, index) => ItemWidget(items[index]),
|
|
378
|
+
separatorBuilder: (context, index) => const Divider(),
|
|
379
|
+
)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Image Optimization
|
|
383
|
+
|
|
384
|
+
```dart
|
|
385
|
+
// ❌ WRONG: No caching, full resolution
|
|
386
|
+
Image.network(url)
|
|
387
|
+
|
|
388
|
+
// ✅ CORRECT: Cached with proper sizing
|
|
389
|
+
CachedNetworkImage(
|
|
390
|
+
imageUrl: url,
|
|
391
|
+
width: 100,
|
|
392
|
+
height: 100,
|
|
393
|
+
fit: BoxFit.cover,
|
|
394
|
+
memCacheWidth: 200, // Cache at 2x for retina
|
|
395
|
+
memCacheHeight: 200,
|
|
396
|
+
placeholder: (context, url) => const Skeleton(),
|
|
397
|
+
errorWidget: (context, url, error) => const Icon(Icons.error),
|
|
398
|
+
)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Dispose Pattern
|
|
402
|
+
|
|
403
|
+
```dart
|
|
404
|
+
class MyWidget extends StatefulWidget {
|
|
405
|
+
@override
|
|
406
|
+
State<MyWidget> createState() => _MyWidgetState();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
class _MyWidgetState extends State<MyWidget> {
|
|
410
|
+
late final StreamSubscription _subscription;
|
|
411
|
+
late final AnimationController _controller;
|
|
412
|
+
late final TextEditingController _textController;
|
|
413
|
+
|
|
414
|
+
@override
|
|
415
|
+
void initState() {
|
|
416
|
+
super.initState();
|
|
417
|
+
_subscription = stream.listen((_) {});
|
|
418
|
+
_controller = AnimationController(vsync: this);
|
|
419
|
+
_textController = TextEditingController();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@override
|
|
423
|
+
void dispose() {
|
|
424
|
+
// ALWAYS dispose in reverse order of creation
|
|
425
|
+
_textController.dispose();
|
|
426
|
+
_controller.dispose();
|
|
427
|
+
_subscription.cancel();
|
|
428
|
+
super.dispose();
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
@override
|
|
432
|
+
Widget build(BuildContext context) => Container();
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Flutter Performance Checklist
|
|
437
|
+
|
|
438
|
+
```markdown
|
|
439
|
+
## Before Every Widget
|
|
440
|
+
- [ ] const constructor added (if no runtime args)
|
|
441
|
+
- [ ] const keywords on static children
|
|
442
|
+
- [ ] Minimal setState scope
|
|
443
|
+
- [ ] Using selectors for provider watches
|
|
444
|
+
|
|
445
|
+
## Before Every List
|
|
446
|
+
- [ ] Using ListView.builder (NOT ListView with children)
|
|
447
|
+
- [ ] itemExtent provided (if fixed height)
|
|
448
|
+
- [ ] Image caching with size limits
|
|
449
|
+
|
|
450
|
+
## Before Any Animation
|
|
451
|
+
- [ ] Using Impeller (Flutter 3.16+)
|
|
452
|
+
- [ ] Avoiding Opacity widget (use FadeTransition)
|
|
453
|
+
- [ ] TickerProviderStateMixin for AnimationController
|
|
454
|
+
|
|
455
|
+
## Before Any Release
|
|
456
|
+
- [ ] All dispose() methods implemented
|
|
457
|
+
- [ ] No print() in production
|
|
458
|
+
- [ ] Tested in profile/release mode
|
|
459
|
+
- [ ] DevTools performance overlay checked
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## 4. Animation Performance (Both Platforms)
|
|
465
|
+
|
|
466
|
+
### The 60fps Imperative
|
|
467
|
+
|
|
468
|
+
```
|
|
469
|
+
Human eye detects:
|
|
470
|
+
├── < 24 fps → "Slideshow" (broken)
|
|
471
|
+
├── 24-30 fps → "Choppy" (uncomfortable)
|
|
472
|
+
├── 30-45 fps → "Noticeably not smooth"
|
|
473
|
+
├── 45-60 fps → "Smooth" (acceptable)
|
|
474
|
+
├── 60 fps → "Buttery" (target)
|
|
475
|
+
└── 120 fps → "Premium" (ProMotion devices)
|
|
476
|
+
|
|
477
|
+
NEVER ship < 60fps animations.
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### GPU vs CPU Animation
|
|
481
|
+
|
|
482
|
+
```
|
|
483
|
+
GPU-ACCELERATED (FAST): CPU-BOUND (SLOW):
|
|
484
|
+
├── transform: translate ├── width, height
|
|
485
|
+
├── transform: scale ├── top, left, right, bottom
|
|
486
|
+
├── transform: rotate ├── margin, padding
|
|
487
|
+
├── opacity ├── border-radius (animated)
|
|
488
|
+
└── (Composited, off main) └── box-shadow (animated)
|
|
489
|
+
|
|
490
|
+
RULE: Only animate transform and opacity.
|
|
491
|
+
Everything else causes layout recalculation.
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### Animation Timing Guide
|
|
495
|
+
|
|
496
|
+
| Animation Type | Duration | Easing |
|
|
497
|
+
|----------------|----------|--------|
|
|
498
|
+
| Micro-interaction | 100-200ms | ease-out |
|
|
499
|
+
| Standard transition | 200-300ms | ease-out |
|
|
500
|
+
| Page transition | 300-400ms | ease-in-out |
|
|
501
|
+
| Complex/dramatic | 400-600ms | ease-in-out |
|
|
502
|
+
| Loading skeletons | 1000-1500ms | linear (loop) |
|
|
503
|
+
|
|
504
|
+
### Spring Physics
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
// React Native Reanimated
|
|
508
|
+
withSpring(targetValue, {
|
|
509
|
+
damping: 15, // How quickly it settles (higher = faster stop)
|
|
510
|
+
stiffness: 150, // How "tight" the spring (higher = faster)
|
|
511
|
+
mass: 1, // Weight of the object
|
|
512
|
+
})
|
|
513
|
+
|
|
514
|
+
// Flutter
|
|
515
|
+
SpringSimulation(
|
|
516
|
+
SpringDescription(
|
|
517
|
+
mass: 1,
|
|
518
|
+
stiffness: 150,
|
|
519
|
+
damping: 15,
|
|
520
|
+
),
|
|
521
|
+
start,
|
|
522
|
+
end,
|
|
523
|
+
velocity,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
// Natural feel ranges:
|
|
527
|
+
// Damping: 10-20 (bouncy to settled)
|
|
528
|
+
// Stiffness: 100-200 (loose to tight)
|
|
529
|
+
// Mass: 0.5-2 (light to heavy)
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## 5. Memory Management
|
|
535
|
+
|
|
536
|
+
### Common Memory Leaks
|
|
537
|
+
|
|
538
|
+
| Source | Platform | Solution |
|
|
539
|
+
|--------|----------|----------|
|
|
540
|
+
| Timers | Both | Clear in cleanup/dispose |
|
|
541
|
+
| Event listeners | Both | Remove in cleanup/dispose |
|
|
542
|
+
| Subscriptions | Both | Cancel in cleanup/dispose |
|
|
543
|
+
| Large images | Both | Limit cache, resize |
|
|
544
|
+
| Async after unmount | RN | isMounted check or AbortController |
|
|
545
|
+
| Animation controllers | Flutter | Dispose controllers |
|
|
546
|
+
|
|
547
|
+
### Image Memory
|
|
548
|
+
|
|
549
|
+
```
|
|
550
|
+
Image memory = width × height × 4 bytes (RGBA)
|
|
551
|
+
|
|
552
|
+
1080p image = 1920 × 1080 × 4 = 8.3 MB
|
|
553
|
+
4K image = 3840 × 2160 × 4 = 33.2 MB
|
|
554
|
+
|
|
555
|
+
10 4K images = 332 MB → App crash!
|
|
556
|
+
|
|
557
|
+
RULE: Always resize images to display size (or 2-3x for retina).
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### Memory Profiling
|
|
561
|
+
|
|
562
|
+
```
|
|
563
|
+
React Native:
|
|
564
|
+
├── Flipper → Memory tab
|
|
565
|
+
├── Xcode Instruments (iOS)
|
|
566
|
+
└── Android Studio Profiler
|
|
567
|
+
|
|
568
|
+
Flutter:
|
|
569
|
+
├── DevTools → Memory tab
|
|
570
|
+
├── Observatory
|
|
571
|
+
└── flutter run --profile
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 6. Battery Optimization
|
|
577
|
+
|
|
578
|
+
### Battery Drain Sources
|
|
579
|
+
|
|
580
|
+
| Source | Impact | Mitigation |
|
|
581
|
+
|--------|--------|------------|
|
|
582
|
+
| **Screen on** | 🔴 Highest | Dark mode on OLED |
|
|
583
|
+
| **GPS continuous** | 🔴 Very high | Use significant change |
|
|
584
|
+
| **Network requests** | 🟡 High | Batch, cache aggressively |
|
|
585
|
+
| **Animations** | 🟡 Medium | Reduce when low battery |
|
|
586
|
+
| **Background work** | 🟡 Medium | Defer non-critical |
|
|
587
|
+
| **CPU computation** | 🟢 Lower | Offload to backend |
|
|
588
|
+
|
|
589
|
+
### OLED Battery Saving
|
|
590
|
+
|
|
591
|
+
```
|
|
592
|
+
OLED screens: Black pixels = OFF = 0 power
|
|
593
|
+
|
|
594
|
+
Dark mode savings:
|
|
595
|
+
├── True black (#000000) → Maximum savings
|
|
596
|
+
├── Dark gray (#1a1a1a) → Slight savings
|
|
597
|
+
├── Any color → Some power
|
|
598
|
+
└── White (#FFFFFF) → Maximum power
|
|
599
|
+
|
|
600
|
+
RULE: On dark mode, use true black for backgrounds.
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### Background Task Guidelines
|
|
604
|
+
|
|
605
|
+
```
|
|
606
|
+
iOS:
|
|
607
|
+
├── Background refresh: Limited, system-scheduled
|
|
608
|
+
├── Push notifications: Use for important updates
|
|
609
|
+
├── Background modes: Location, audio, VoIP only
|
|
610
|
+
└── Background tasks: Max ~30 seconds
|
|
611
|
+
|
|
612
|
+
Android:
|
|
613
|
+
├── WorkManager: System-scheduled, battery-aware
|
|
614
|
+
├── Foreground service: Visible to user, continuous
|
|
615
|
+
├── JobScheduler: Batch network operations
|
|
616
|
+
└── Doze mode: Respect it, batch operations
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
## 7. Network Performance
|
|
622
|
+
|
|
623
|
+
### Offline-First Architecture
|
|
624
|
+
|
|
625
|
+
```
|
|
626
|
+
┌──────────────┐
|
|
627
|
+
│ UI │
|
|
628
|
+
└──────┬───────┘
|
|
629
|
+
│
|
|
630
|
+
┌──────▼───────┐
|
|
631
|
+
│ Cache │ ← Read from cache FIRST
|
|
632
|
+
└──────┬───────┘
|
|
633
|
+
│
|
|
634
|
+
┌──────▼───────┐
|
|
635
|
+
│ Network │ ← Update cache from network
|
|
636
|
+
└──────────────┘
|
|
637
|
+
|
|
638
|
+
Benefits:
|
|
639
|
+
├── Instant UI (no loading spinner for cached data)
|
|
640
|
+
├── Works offline
|
|
641
|
+
├── Reduces data usage
|
|
642
|
+
└── Better UX on slow networks
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Request Optimization
|
|
646
|
+
|
|
647
|
+
```
|
|
648
|
+
BATCH: Combine multiple requests into one
|
|
649
|
+
├── 10 small requests → 1 batch request
|
|
650
|
+
├── Reduces connection overhead
|
|
651
|
+
└── Better for battery (radio on once)
|
|
652
|
+
|
|
653
|
+
CACHE: Don't re-fetch unchanged data
|
|
654
|
+
├── ETag/If-None-Match headers
|
|
655
|
+
├── Cache-Control headers
|
|
656
|
+
└── Stale-while-revalidate pattern
|
|
657
|
+
|
|
658
|
+
COMPRESS: Reduce payload size
|
|
659
|
+
├── gzip/brotli compression
|
|
660
|
+
├── Request only needed fields (GraphQL)
|
|
661
|
+
└── Paginate large lists
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## 8. Performance Testing
|
|
667
|
+
|
|
668
|
+
### What to Test
|
|
669
|
+
|
|
670
|
+
| Metric | Target | Tool |
|
|
671
|
+
|--------|--------|------|
|
|
672
|
+
| **Frame rate** | ≥ 60fps | Performance overlay |
|
|
673
|
+
| **Memory** | Stable, no growth | Profiler |
|
|
674
|
+
| **Cold start** | < 2s | Manual timing |
|
|
675
|
+
| **TTI (Time to Interactive)** | < 3s | Lighthouse |
|
|
676
|
+
| **List scroll** | No jank | Manual feel |
|
|
677
|
+
| **Animation smoothness** | No drops | Performance monitor |
|
|
678
|
+
|
|
679
|
+
### Test on Real Devices
|
|
680
|
+
|
|
681
|
+
```
|
|
682
|
+
⚠️ NEVER trust only:
|
|
683
|
+
├── Simulator/emulator (faster than real)
|
|
684
|
+
├── Dev mode (slower than release)
|
|
685
|
+
├── High-end devices only
|
|
686
|
+
|
|
687
|
+
✅ ALWAYS test on:
|
|
688
|
+
├── Low-end Android (< $200 phone)
|
|
689
|
+
├── Older iOS device (iPhone 8 or SE)
|
|
690
|
+
├── Release/profile build
|
|
691
|
+
└── With real data (not 10 items)
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Performance Monitoring Checklist
|
|
695
|
+
|
|
696
|
+
```markdown
|
|
697
|
+
## During Development
|
|
698
|
+
- [ ] Performance overlay enabled
|
|
699
|
+
- [ ] Watching for dropped frames
|
|
700
|
+
- [ ] Memory usage stable
|
|
701
|
+
- [ ] No console warnings about performance
|
|
702
|
+
|
|
703
|
+
## Before Release
|
|
704
|
+
- [ ] Tested on low-end device
|
|
705
|
+
- [ ] Profiled memory over extended use
|
|
706
|
+
- [ ] Cold start time measured
|
|
707
|
+
- [ ] List scroll tested with 1000+ items
|
|
708
|
+
- [ ] Animations tested at 60fps
|
|
709
|
+
- [ ] Network tested on slow 3G
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## 9. Quick Reference Card
|
|
715
|
+
|
|
716
|
+
### React Native Essentials
|
|
717
|
+
|
|
718
|
+
```javascript
|
|
719
|
+
// List: Always use
|
|
720
|
+
<FlatList
|
|
721
|
+
data={data}
|
|
722
|
+
renderItem={useCallback(({item}) => <MemoItem item={item} />, [])}
|
|
723
|
+
keyExtractor={useCallback(item => item.id, [])}
|
|
724
|
+
getItemLayout={useCallback((_, i) => ({length: H, offset: H*i, index: i}), [])}
|
|
725
|
+
/>
|
|
726
|
+
|
|
727
|
+
// Animation: Always native
|
|
728
|
+
useNativeDriver: true
|
|
729
|
+
|
|
730
|
+
// Cleanup: Always present
|
|
731
|
+
useEffect(() => {
|
|
732
|
+
return () => cleanup();
|
|
733
|
+
}, []);
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Flutter Essentials
|
|
737
|
+
|
|
738
|
+
```dart
|
|
739
|
+
// Widgets: Always const
|
|
740
|
+
const MyWidget()
|
|
741
|
+
|
|
742
|
+
// Lists: Always builder
|
|
743
|
+
ListView.builder(itemBuilder: ...)
|
|
744
|
+
|
|
745
|
+
// State: Always targeted
|
|
746
|
+
ValueListenableBuilder() or ref.watch(provider.select(...))
|
|
747
|
+
|
|
748
|
+
// Dispose: Always cleanup
|
|
749
|
+
@override
|
|
750
|
+
void dispose() {
|
|
751
|
+
controller.dispose();
|
|
752
|
+
super.dispose();
|
|
753
|
+
}
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### Animation Targets
|
|
757
|
+
|
|
758
|
+
```
|
|
759
|
+
Transform/Opacity only ← What to animate
|
|
760
|
+
16.67ms per frame ← Time budget
|
|
761
|
+
60fps minimum ← Target
|
|
762
|
+
Low-end Android ← Test device
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
---
|
|
766
|
+
|
|
767
|
+
> **Remember:** Performance is not optimization—it's baseline quality. A slow app is a broken app. Test on the worst device your users have, not the best device you have.
|