agy-superpowers 5.0.7 → 5.0.9
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/package.json +1 -1
- package/template/agent/rules/superpowers.md +54 -0
- package/template/agent/skills/api-design/SKILL.md +193 -0
- package/template/agent/skills/app-store-optimizer/SKILL.md +127 -0
- package/template/agent/skills/auth-and-identity/SKILL.md +167 -0
- package/template/agent/skills/backend-developer/SKILL.md +148 -0
- package/template/agent/skills/community-manager/SKILL.md +115 -0
- package/template/agent/skills/content-marketer/SKILL.md +111 -0
- package/template/agent/skills/conversion-optimizer/SKILL.md +142 -0
- package/template/agent/skills/copywriter/SKILL.md +114 -0
- package/template/agent/skills/cto-architect/SKILL.md +133 -0
- package/template/agent/skills/customer-success-manager/SKILL.md +126 -0
- package/template/agent/skills/data-analyst/SKILL.md +147 -0
- package/template/agent/skills/devops-engineer/SKILL.md +117 -0
- package/template/agent/skills/email-infrastructure/SKILL.md +164 -0
- package/template/agent/skills/frontend-developer/SKILL.md +172 -0
- package/template/agent/skills/frontend-developer/references/react-nextjs.md +343 -0
- package/template/agent/skills/frontend-developer/references/react-rules/_sections.md +46 -0
- package/template/agent/skills/frontend-developer/references/react-rules/_template.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-event-handler-refs.md +55 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-init-once.md +42 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-use-latest.md +39 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-api-routes.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-defer-await.md +80 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-dependencies.md +51 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-parallel.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-suspense-boundaries.md +99 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-barrel-imports.md +59 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-conditional.md +31 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-defer-third-party.md +49 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-dynamic-imports.md +35 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-preload.md +50 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-event-listeners.md +74 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-localstorage-schema.md +71 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-passive-event-listeners.md +48 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-swr-dedup.md +56 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-batch-dom-css.md +107 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-function-results.md +80 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-property-access.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-storage.md +70 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-combine-iterations.md +32 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-early-exit.md +50 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-flatmap-filter.md +60 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-hoist-regexp.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-index-maps.md +37 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-length-check-first.md +49 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-min-max-loop.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-set-map-lookups.md +24 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-tosorted-immutable.md +57 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-activity.md +26 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-conditional-render.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-content-visibility.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hoist-jsx.md +46 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-no-flicker.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-suppress-warning.md +30 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-resource-hints.md +85 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-script-defer-async.md +68 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-svg-precision.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-usetransition-loading.md +75 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-defer-reads.md +39 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-dependencies.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state-no-effect.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state.md +29 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-functional-setstate.md +74 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-lazy-state-init.md +58 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo-with-default-value.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo.md +44 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-move-effect-to-event.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-no-inline-components.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-simple-expression-in-memo.md +35 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-split-combined-hooks.md +64 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-transitions.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-deferred-value.md +59 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-ref-transient-values.md +73 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-after-nonblocking.md +73 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-auth-actions.md +96 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-cache-lru.md +41 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-cache-react.md +76 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-dedup-props.md +65 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-hoist-static-io.md +142 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-parallel-fetching.md +83 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-serialization.md +38 -0
- package/template/agent/skills/frontend-developer/references/svelte-sveltekit.md +220 -0
- package/template/agent/skills/frontend-developer/references/vanilla.md +275 -0
- package/template/agent/skills/frontend-developer/references/vue-nuxt.md +289 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/_index.md +154 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-class-based-technique.md +254 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-state-driven-technique.md +291 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-async.md +97 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-data-flow.md +307 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-fallthrough-attrs.md +174 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-keep-alive.md +137 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-slots.md +216 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-suspense.md +228 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-teleport.md +108 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition-group.md +128 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition.md +125 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/composables.md +290 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/directives.md +162 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-v-once-v-memo-directives.md +182 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-virtualize-large-lists.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/plugins.md +166 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/reactivity.md +344 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/render-functions.md +201 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/sfc.md +310 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/state-management.md +135 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/updated-hook-performance.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/_index.md +23 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforeenter-no-param-trigger.md +167 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforerouteenter-no-this.md +176 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-guard-async-await-pattern.md +227 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-infinite-loop.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-next-deprecated.md +150 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-param-change-no-lifecycle.md +181 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-simple-routing-cleanup.md +209 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-use-vue-router-for-production.md +183 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/_index.md +29 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/async-component-testing.md +163 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/teleport-testing-complexity.md +158 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-async-await-flushpromises.md +175 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-browser-vs-node-runners.md +208 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-component-blackbox-approach.md +144 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-composables-helper-wrapper.md +238 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-e2e-playwright-recommended.md +242 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-no-snapshot-only.md +197 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-pinia-store-setup.md +228 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-suspense-async-components.md +229 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-vitest-recommended-for-vue.md +204 -0
- package/template/agent/skills/game-design/SKILL.md +194 -0
- package/template/agent/skills/game-developer/SKILL.md +175 -0
- package/template/agent/skills/growth-hacker/SKILL.md +122 -0
- package/template/agent/skills/i18n-localization/SKILL.md +126 -0
- package/template/agent/skills/influencer-marketer/SKILL.md +141 -0
- package/template/agent/skills/mobile-developer/SKILL.md +194 -0
- package/template/agent/skills/mobile-developer/references/android-native.md +396 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-accessibility.md +36 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-architecture.md +52 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-coroutines.md +139 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-data-layer.md +51 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-emulator-skill.md +108 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-gradle-logic.md +126 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-retrofit.md +142 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-testing.md +102 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-viewmodel.md +43 -0
- package/template/agent/skills/mobile-developer/references/android-rules/coil-compose.md +74 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-navigation.md +422 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-performance-audit.md +199 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-ui.md +49 -0
- package/template/agent/skills/mobile-developer/references/android-rules/gradle-build-performance.md +346 -0
- package/template/agent/skills/mobile-developer/references/android-rules/kotlin-concurrency-expert.md +169 -0
- package/template/agent/skills/mobile-developer/references/android-rules/rxjava-to-coroutines-migration.md +101 -0
- package/template/agent/skills/mobile-developer/references/android-rules/xml-to-compose-migration.md +338 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-best-practices.md +52 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-checks-migration.md +134 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-cli-app-best-practices.md +123 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-doc-validation.md +45 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-matcher-best-practices.md +106 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-modern-features.md +241 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-package-maintenance.md +75 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-test-fundamentals.md +124 -0
- package/template/agent/skills/mobile-developer/references/flutter.md +291 -0
- package/template/agent/skills/mobile-developer/references/ios-native.md +358 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/accessibility-patterns.md +215 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-advanced.md +403 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-basics.md +284 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-transitions.md +326 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/charts-accessibility.md +135 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/charts.md +602 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/image-optimization.md +203 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/latest-apis.md +464 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/layout-best-practices.md +266 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/liquid-glass.md +416 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/list-patterns.md +394 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-scenes.md +318 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-views.md +357 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-window-styling.md +303 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/performance-patterns.md +403 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/scroll-patterns.md +293 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/sheet-navigation-patterns.md +363 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/state-management.md +417 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/view-structure.md +389 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/_sections.md +86 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/_template.md +28 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-derived-value.md +53 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gesture-detector-press.md +95 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gpu-properties.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/design-system-compound-components.md +66 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/fonts-config-plugin.md +71 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/imports-design-system-folder.md +68 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/js-hoist-intl.md +61 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-callbacks.md +44 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-function-references.md +132 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-images.md +53 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-inline-objects.md +97 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-expensive.md +94 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-memo.md +82 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-types.md +104 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-virtualize.md +67 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-native-deps-in-app.md +46 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-single-dependency-versions.md +63 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/navigation-native-navigators.md +188 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-destructure-functions.md +50 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-reanimated-shared-values.md +48 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-dispatcher.md +91 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-fallback.md +56 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-minimize.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-no-falsy-and.md +74 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-text-in-text-component.md +36 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/scroll-position-no-state.md +82 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/state-ground-truth.md +80 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-expo-image.md +66 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-image-gallery.md +104 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-measure-views.md +78 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-menus.md +174 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-native-modals.md +77 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-pressable.md +61 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-safe-area-scroll.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-scrollview-content-inset.md +45 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-styling.md +87 -0
- package/template/agent/skills/mobile-developer/references/react-native.md +345 -0
- package/template/agent/skills/monetization-strategist/SKILL.md +119 -0
- package/template/agent/skills/paid-acquisition-specialist/SKILL.md +119 -0
- package/template/agent/skills/product-manager/SKILL.md +105 -0
- package/template/agent/skills/real-time-features/SKILL.md +194 -0
- package/template/agent/skills/retention-specialist/SKILL.md +123 -0
- package/template/agent/skills/saas-architect/SKILL.md +139 -0
- package/template/agent/skills/security-engineer/SKILL.md +133 -0
- package/template/agent/skills/seo-specialist/SKILL.md +130 -0
- package/template/agent/skills/subscription-billing/SKILL.md +179 -0
- package/template/agent/skills/ux-designer/SKILL.md +128 -0
package/template/agent/skills/mobile-developer/references/android-rules/gradle-build-performance.md
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gradle-build-performance
|
|
3
|
+
description: Debug and optimize Android/Gradle build performance. Use when builds are slow, investigating CI/CD performance, analyzing build scans, or identifying compilation bottlenecks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gradle Build Performance
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
- Build times are slow (clean or incremental)
|
|
11
|
+
- Investigating build performance regressions
|
|
12
|
+
- Analyzing Gradle Build Scans
|
|
13
|
+
- Identifying configuration vs execution bottlenecks
|
|
14
|
+
- Optimizing CI/CD build times
|
|
15
|
+
- Enabling Gradle Configuration Cache
|
|
16
|
+
- Reducing unnecessary recompilation
|
|
17
|
+
- Debugging kapt/KSP annotation processing
|
|
18
|
+
|
|
19
|
+
## Example Prompts
|
|
20
|
+
|
|
21
|
+
- "My builds are slow, how can I speed them up?"
|
|
22
|
+
- "How do I analyze a Gradle build scan?"
|
|
23
|
+
- "Why is configuration taking so long?"
|
|
24
|
+
- "Why does my project always recompile everything?"
|
|
25
|
+
- "How do I enable configuration cache?"
|
|
26
|
+
- "Why is kapt so slow?"
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Workflow
|
|
31
|
+
|
|
32
|
+
1. **Measure Baseline** — Clean build + incremental build times
|
|
33
|
+
2. **Generate Build Scan** — `./gradlew assembleDebug --scan`
|
|
34
|
+
3. **Identify Phase** — Configuration? Execution? Dependency resolution?
|
|
35
|
+
4. **Apply ONE optimization** — Don't batch changes
|
|
36
|
+
5. **Measure Improvement** — Compare against baseline
|
|
37
|
+
6. **Verify in Build Scan** — Visual confirmation
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Quick Diagnostics
|
|
42
|
+
|
|
43
|
+
### Generate Build Scan
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
./gradlew assembleDebug --scan
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Profile Build Locally
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
./gradlew assembleDebug --profile
|
|
53
|
+
# Opens report in build/reports/profile/
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Build Timing Summary
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
./gradlew assembleDebug --info | grep -E "^\:.*"
|
|
60
|
+
# Or view in Android Studio: Build > Analyze APK Build
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Build Phases
|
|
66
|
+
|
|
67
|
+
| Phase | What Happens | Common Issues |
|
|
68
|
+
|-------|--------------|---------------|
|
|
69
|
+
| **Initialization** | `settings.gradle.kts` evaluated | Too many `include()` statements |
|
|
70
|
+
| **Configuration** | All `build.gradle.kts` files evaluated | Expensive plugins, eager task creation |
|
|
71
|
+
| **Execution** | Tasks run based on inputs/outputs | Cache misses, non-incremental tasks |
|
|
72
|
+
|
|
73
|
+
### Identify the Bottleneck
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Build scan → Performance → Build timeline
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- **Long configuration phase**: Focus on plugin and buildscript optimization
|
|
80
|
+
- **Long execution phase**: Focus on task caching and parallelization
|
|
81
|
+
- **Dependency resolution slow**: Focus on repository configuration
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 12 Optimization Patterns
|
|
86
|
+
|
|
87
|
+
### 1. Enable Configuration Cache
|
|
88
|
+
|
|
89
|
+
Caches configuration phase across builds (AGP 8.0+):
|
|
90
|
+
|
|
91
|
+
```properties
|
|
92
|
+
# gradle.properties
|
|
93
|
+
org.gradle.configuration-cache=true
|
|
94
|
+
org.gradle.configuration-cache.problems=warn
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Enable Build Cache
|
|
98
|
+
|
|
99
|
+
Reuses task outputs across builds and machines:
|
|
100
|
+
|
|
101
|
+
```properties
|
|
102
|
+
# gradle.properties
|
|
103
|
+
org.gradle.caching=true
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 3. Enable Parallel Execution
|
|
107
|
+
|
|
108
|
+
Build independent modules simultaneously:
|
|
109
|
+
|
|
110
|
+
```properties
|
|
111
|
+
# gradle.properties
|
|
112
|
+
org.gradle.parallel=true
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4. Increase JVM Heap
|
|
116
|
+
|
|
117
|
+
Allocate more memory for large projects:
|
|
118
|
+
|
|
119
|
+
```properties
|
|
120
|
+
# gradle.properties
|
|
121
|
+
org.gradle.jvmargs=-Xmx4g -XX:+UseParallelGC
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 5. Use Non-Transitive R Classes
|
|
125
|
+
|
|
126
|
+
Reduces R class size and compilation (AGP 8.0+ default):
|
|
127
|
+
|
|
128
|
+
```properties
|
|
129
|
+
# gradle.properties
|
|
130
|
+
android.nonTransitiveRClass=true
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 6. Migrate kapt to KSP
|
|
134
|
+
|
|
135
|
+
KSP is 2x faster than kapt for Kotlin:
|
|
136
|
+
|
|
137
|
+
```kotlin
|
|
138
|
+
// Before (slow)
|
|
139
|
+
kapt("com.google.dagger:hilt-compiler:2.51.1")
|
|
140
|
+
|
|
141
|
+
// After (fast)
|
|
142
|
+
ksp("com.google.dagger:hilt-compiler:2.51.1")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 7. Avoid Dynamic Dependencies
|
|
146
|
+
|
|
147
|
+
Pin dependency versions:
|
|
148
|
+
|
|
149
|
+
```kotlin
|
|
150
|
+
// BAD: Forces resolution every build
|
|
151
|
+
implementation("com.example:lib:+")
|
|
152
|
+
implementation("com.example:lib:1.0.+")
|
|
153
|
+
|
|
154
|
+
// GOOD: Fixed version
|
|
155
|
+
implementation("com.example:lib:1.2.3")
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### 8. Optimize Repository Order
|
|
159
|
+
|
|
160
|
+
Put most-used repositories first:
|
|
161
|
+
|
|
162
|
+
```kotlin
|
|
163
|
+
// settings.gradle.kts
|
|
164
|
+
dependencyResolutionManagement {
|
|
165
|
+
repositories {
|
|
166
|
+
google() // First: Android dependencies
|
|
167
|
+
mavenCentral() // Second: Most libraries
|
|
168
|
+
// Third-party repos last
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### 9. Use includeBuild for Local Modules
|
|
174
|
+
|
|
175
|
+
Composite builds are faster than `project()` for large monorepos:
|
|
176
|
+
|
|
177
|
+
```kotlin
|
|
178
|
+
// settings.gradle.kts
|
|
179
|
+
includeBuild("shared-library") {
|
|
180
|
+
dependencySubstitution {
|
|
181
|
+
substitute(module("com.example:shared")).using(project(":"))
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 10. Enable Incremental Annotation Processing
|
|
187
|
+
|
|
188
|
+
```properties
|
|
189
|
+
# gradle.properties
|
|
190
|
+
kapt.incremental.apt=true
|
|
191
|
+
kapt.use.worker.api=true
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 11. Avoid Configuration-Time I/O
|
|
195
|
+
|
|
196
|
+
Don't read files or make network calls during configuration:
|
|
197
|
+
|
|
198
|
+
```kotlin
|
|
199
|
+
// BAD: Runs during configuration
|
|
200
|
+
val version = file("version.txt").readText()
|
|
201
|
+
|
|
202
|
+
// GOOD: Defer to execution
|
|
203
|
+
val version = providers.fileContents(file("version.txt")).asText
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 12. Use Lazy Task Configuration
|
|
207
|
+
|
|
208
|
+
Avoid `create()`, use `register()`:
|
|
209
|
+
|
|
210
|
+
```kotlin
|
|
211
|
+
// BAD: Eagerly configured
|
|
212
|
+
tasks.create("myTask") { ... }
|
|
213
|
+
|
|
214
|
+
// GOOD: Lazily configured
|
|
215
|
+
tasks.register("myTask") { ... }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Common Bottleneck Analysis
|
|
221
|
+
|
|
222
|
+
### Slow Configuration Phase
|
|
223
|
+
|
|
224
|
+
**Symptoms**: Build scan shows long "Configuring build" time
|
|
225
|
+
|
|
226
|
+
**Causes & Fixes**:
|
|
227
|
+
| Cause | Fix |
|
|
228
|
+
|-------|-----|
|
|
229
|
+
| Eager task creation | Use `tasks.register()` instead of `tasks.create()` |
|
|
230
|
+
| buildSrc with many dependencies | Migrate to Convention Plugins with `includeBuild` |
|
|
231
|
+
| File I/O in build scripts | Use `providers.fileContents()` |
|
|
232
|
+
| Network calls in plugins | Cache results or use offline mode |
|
|
233
|
+
|
|
234
|
+
### Slow Compilation
|
|
235
|
+
|
|
236
|
+
**Symptoms**: `:app:compileDebugKotlin` takes too long
|
|
237
|
+
|
|
238
|
+
**Causes & Fixes**:
|
|
239
|
+
| Cause | Fix |
|
|
240
|
+
|-------|-----|
|
|
241
|
+
| Non-incremental changes | Avoid `build.gradle.kts` changes that invalidate cache |
|
|
242
|
+
| Large modules | Break into smaller feature modules |
|
|
243
|
+
| Excessive kapt usage | Migrate to KSP |
|
|
244
|
+
| Kotlin compiler memory | Increase `kotlin.daemon.jvmargs` |
|
|
245
|
+
|
|
246
|
+
### Cache Misses
|
|
247
|
+
|
|
248
|
+
**Symptoms**: Tasks always rerun despite no changes
|
|
249
|
+
|
|
250
|
+
**Causes & Fixes**:
|
|
251
|
+
| Cause | Fix |
|
|
252
|
+
|-------|-----|
|
|
253
|
+
| Unstable task inputs | Use `@PathSensitive`, `@NormalizeLineEndings` |
|
|
254
|
+
| Absolute paths in outputs | Use relative paths |
|
|
255
|
+
| Missing `@CacheableTask` | Add annotation to custom tasks |
|
|
256
|
+
| Different JDK versions | Standardize JDK across environments |
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## CI/CD Optimizations
|
|
261
|
+
|
|
262
|
+
### Remote Build Cache
|
|
263
|
+
|
|
264
|
+
```kotlin
|
|
265
|
+
// settings.gradle.kts
|
|
266
|
+
buildCache {
|
|
267
|
+
local { isEnabled = true }
|
|
268
|
+
remote<HttpBuildCache> {
|
|
269
|
+
url = uri("https://cache.example.com/")
|
|
270
|
+
isPush = System.getenv("CI") == "true"
|
|
271
|
+
credentials {
|
|
272
|
+
username = System.getenv("CACHE_USER")
|
|
273
|
+
password = System.getenv("CACHE_PASS")
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Gradle Enterprise / Develocity
|
|
280
|
+
|
|
281
|
+
For advanced build analytics:
|
|
282
|
+
|
|
283
|
+
```kotlin
|
|
284
|
+
// settings.gradle.kts
|
|
285
|
+
plugins {
|
|
286
|
+
id("com.gradle.develocity") version "3.17"
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
develocity {
|
|
290
|
+
buildScan {
|
|
291
|
+
termsOfUseUrl.set("https://gradle.com/help/legal-terms-of-use")
|
|
292
|
+
termsOfUseAgree.set("yes")
|
|
293
|
+
publishing.onlyIf { System.getenv("CI") != null }
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Skip Unnecessary Tasks in CI
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Skip tests for UI-only changes
|
|
302
|
+
./gradlew assembleDebug -x test -x lint
|
|
303
|
+
|
|
304
|
+
# Only run affected module tests
|
|
305
|
+
./gradlew :feature:login:test
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Android Studio Settings
|
|
311
|
+
|
|
312
|
+
### File → Settings → Build → Gradle
|
|
313
|
+
|
|
314
|
+
- **Gradle JDK**: Match your project's JDK
|
|
315
|
+
- **Build and run using**: Gradle (not IntelliJ)
|
|
316
|
+
- **Run tests using**: Gradle
|
|
317
|
+
|
|
318
|
+
### File → Settings → Build → Compiler
|
|
319
|
+
|
|
320
|
+
- **Compile independent modules in parallel**: ✅ Enabled
|
|
321
|
+
- **Configure on demand**: ❌ Disabled (deprecated)
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Verification Checklist
|
|
326
|
+
|
|
327
|
+
After optimizations, verify:
|
|
328
|
+
|
|
329
|
+
- [ ] Configuration cache enabled and working
|
|
330
|
+
- [ ] Build cache hit rate > 80% (check build scan)
|
|
331
|
+
- [ ] No dynamic dependency versions
|
|
332
|
+
- [ ] KSP used instead of kapt where possible
|
|
333
|
+
- [ ] Parallel execution enabled
|
|
334
|
+
- [ ] JVM memory tuned appropriately
|
|
335
|
+
- [ ] CI remote cache configured
|
|
336
|
+
- [ ] No configuration-time I/O
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## References
|
|
341
|
+
|
|
342
|
+
- [Optimize Build Speed](https://developer.android.com/build/optimize-your-build)
|
|
343
|
+
- [Gradle Configuration Cache](https://docs.gradle.org/current/userguide/configuration_cache.html)
|
|
344
|
+
- [Gradle Build Cache](https://docs.gradle.org/current/userguide/build_cache.html)
|
|
345
|
+
- [Migrate from kapt to KSP](https://developer.android.com/build/migrate-to-ksp)
|
|
346
|
+
- [Gradle Build Scans](https://scans.gradle.com/)
|
package/template/agent/skills/mobile-developer/references/android-rules/kotlin-concurrency-expert.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin-concurrency-expert
|
|
3
|
+
description: Kotlin Coroutines review and remediation for Android. Use when asked to review concurrency usage, fix coroutine-related bugs, improve thread safety, or resolve lifecycle issues in Kotlin/Android code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kotlin Concurrency Expert
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Review and fix Kotlin Coroutines issues in Android codebases by applying structured concurrency, lifecycle safety, proper scoping, and modern best practices with minimal behavior changes.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
### 1. Triage the Issue
|
|
15
|
+
|
|
16
|
+
- Capture the exact error, crash, or symptom (ANR, memory leak, race condition, incorrect state).
|
|
17
|
+
- Check project coroutines setup: `kotlinx-coroutines-android` version, `lifecycle-runtime-ktx` version.
|
|
18
|
+
- Identify the current scope context (`viewModelScope`, `lifecycleScope`, custom scope, or none).
|
|
19
|
+
- Confirm whether the code is UI-bound (`Dispatchers.Main`) or intended to run off the main thread (`Dispatchers.IO`, `Dispatchers.Default`).
|
|
20
|
+
- Verify Dispatcher injection patterns for testability.
|
|
21
|
+
|
|
22
|
+
### 2. Apply the Smallest Safe Fix
|
|
23
|
+
|
|
24
|
+
Prefer edits that preserve existing behavior while satisfying structured concurrency and lifecycle safety.
|
|
25
|
+
|
|
26
|
+
Common fixes:
|
|
27
|
+
|
|
28
|
+
- **ANR / Main thread blocking**: Move heavy work to `withContext(Dispatchers.IO)` or `Dispatchers.Default`; ensure suspend functions are main-safe.
|
|
29
|
+
- **Memory leaks / zombie coroutines**: Replace `GlobalScope` with a lifecycle-bound scope (`viewModelScope`, `lifecycleScope`, or injected `applicationScope`).
|
|
30
|
+
- **Lifecycle collection issues**: Replace deprecated `launchWhenStarted` with `repeatOnLifecycle(Lifecycle.State.STARTED)`.
|
|
31
|
+
- **State exposure**: Encapsulate `MutableStateFlow` / `MutableSharedFlow`; expose read-only `StateFlow` or `Flow`.
|
|
32
|
+
- **CancellationException swallowing**: Ensure generic `catch (e: Exception)` blocks rethrow `CancellationException`.
|
|
33
|
+
- **Non-cooperative cancellation**: Add `ensureActive()` or `yield()` in tight loops for cooperative cancellation.
|
|
34
|
+
- **Callback APIs**: Convert listeners to `callbackFlow` with proper `awaitClose` cleanup.
|
|
35
|
+
- **Hardcoded Dispatchers**: Inject `CoroutineDispatcher` via constructor for testability.
|
|
36
|
+
|
|
37
|
+
## Critical Rules
|
|
38
|
+
|
|
39
|
+
### Dispatcher Injection (Testability)
|
|
40
|
+
|
|
41
|
+
```kotlin
|
|
42
|
+
// CORRECT: Inject dispatcher
|
|
43
|
+
class UserRepository(
|
|
44
|
+
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
|
|
45
|
+
) {
|
|
46
|
+
suspend fun fetchUser() = withContext(ioDispatcher) { ... }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// INCORRECT: Hardcoded dispatcher
|
|
50
|
+
class UserRepository {
|
|
51
|
+
suspend fun fetchUser() = withContext(Dispatchers.IO) { ... }
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Lifecycle-Aware Collection
|
|
56
|
+
|
|
57
|
+
```kotlin
|
|
58
|
+
// CORRECT: Use repeatOnLifecycle
|
|
59
|
+
viewLifecycleOwner.lifecycleScope.launch {
|
|
60
|
+
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
61
|
+
viewModel.uiState.collect { state -> updateUI(state) }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// INCORRECT: Direct collection (unsafe, deprecated)
|
|
66
|
+
lifecycleScope.launchWhenStarted {
|
|
67
|
+
viewModel.uiState.collect { state -> updateUI(state) }
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### State Encapsulation
|
|
72
|
+
|
|
73
|
+
```kotlin
|
|
74
|
+
// CORRECT: Expose read-only StateFlow
|
|
75
|
+
class MyViewModel : ViewModel() {
|
|
76
|
+
private val _uiState = MutableStateFlow(UiState())
|
|
77
|
+
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// INCORRECT: Exposed mutable state
|
|
81
|
+
class MyViewModel : ViewModel() {
|
|
82
|
+
val uiState = MutableStateFlow(UiState()) // Leaks mutability
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Exception Handling
|
|
87
|
+
|
|
88
|
+
```kotlin
|
|
89
|
+
// CORRECT: Rethrow CancellationException
|
|
90
|
+
try {
|
|
91
|
+
doSuspendWork()
|
|
92
|
+
} catch (e: CancellationException) {
|
|
93
|
+
throw e // Must rethrow!
|
|
94
|
+
} catch (e: Exception) {
|
|
95
|
+
handleError(e)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// INCORRECT: Swallows cancellation
|
|
99
|
+
try {
|
|
100
|
+
doSuspendWork()
|
|
101
|
+
} catch (e: Exception) {
|
|
102
|
+
handleError(e) // CancellationException swallowed!
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Cooperative Cancellation
|
|
107
|
+
|
|
108
|
+
```kotlin
|
|
109
|
+
// CORRECT: Check for cancellation in tight loops
|
|
110
|
+
suspend fun processLargeList(items: List<Item>) {
|
|
111
|
+
items.forEach { item ->
|
|
112
|
+
ensureActive() // Check cancellation
|
|
113
|
+
processItem(item)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// INCORRECT: Non-cooperative (ignores cancellation)
|
|
118
|
+
suspend fun processLargeList(items: List<Item>) {
|
|
119
|
+
items.forEach { item ->
|
|
120
|
+
processItem(item) // Never checks cancellation
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Callback Conversion
|
|
126
|
+
|
|
127
|
+
```kotlin
|
|
128
|
+
// CORRECT: callbackFlow with awaitClose
|
|
129
|
+
fun locationUpdates(): Flow<Location> = callbackFlow {
|
|
130
|
+
val listener = LocationListener { location ->
|
|
131
|
+
trySend(location)
|
|
132
|
+
}
|
|
133
|
+
locationManager.requestLocationUpdates(listener)
|
|
134
|
+
|
|
135
|
+
awaitClose { locationManager.removeUpdates(listener) }
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Scope Guidelines
|
|
140
|
+
|
|
141
|
+
| Scope | Use When | Lifecycle |
|
|
142
|
+
|-------|----------|-----------|
|
|
143
|
+
| `viewModelScope` | ViewModel operations | Cleared with ViewModel |
|
|
144
|
+
| `lifecycleScope` | UI operations in Activity/Fragment | Destroyed with lifecycle owner |
|
|
145
|
+
| `repeatOnLifecycle` | Flow collection in UI | Started/Stopped with lifecycle state |
|
|
146
|
+
| `applicationScope` (injected) | App-wide background work | Application lifetime |
|
|
147
|
+
| `GlobalScope` | **NEVER USE** | Breaks structured concurrency |
|
|
148
|
+
|
|
149
|
+
## Testing Pattern
|
|
150
|
+
|
|
151
|
+
```kotlin
|
|
152
|
+
@Test
|
|
153
|
+
fun `loading data updates state`() = runTest {
|
|
154
|
+
val testDispatcher = StandardTestDispatcher(testScheduler)
|
|
155
|
+
val repository = FakeRepository()
|
|
156
|
+
val viewModel = MyViewModel(repository, testDispatcher)
|
|
157
|
+
|
|
158
|
+
viewModel.loadData()
|
|
159
|
+
advanceUntilIdle()
|
|
160
|
+
|
|
161
|
+
assertEquals(UiState.Success(data), viewModel.uiState.value)
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Reference Material
|
|
166
|
+
|
|
167
|
+
- [Kotlin Coroutines Best Practices](https://developer.android.com/kotlin/coroutines/coroutines-best-practices)
|
|
168
|
+
- [StateFlow and SharedFlow](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow)
|
|
169
|
+
- [repeatOnLifecycle API](https://developer.android.com/topic/libraries/architecture/coroutines#repeatOnLifecycle)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rxjava-to-coroutines-migration
|
|
3
|
+
description: Guide and execute the migration of asynchronous code from RxJava to Kotlin Coroutines and Flow. Use this skill when a user asks to convert RxJava (Observables, Singles, Completables, Subjects) to Coroutines (suspend functions, Flows, StateFlows).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# RxJava to Kotlin Coroutines Migration Skill
|
|
7
|
+
|
|
8
|
+
A specialized skill designed to safely and idiomatically refactor Android or Kotlin codebases from RxJava to Kotlin Coroutines and Flow.
|
|
9
|
+
|
|
10
|
+
## Migration Mapping Guide
|
|
11
|
+
|
|
12
|
+
When migrating RxJava components to Kotlin Coroutines, use the following standard mappings:
|
|
13
|
+
|
|
14
|
+
### 1. Base Types
|
|
15
|
+
- **`Single<T>`** -> `suspend fun ...(): T`
|
|
16
|
+
- A single asynchronous value.
|
|
17
|
+
- **`Maybe<T>`** -> `suspend fun ...(): T?`
|
|
18
|
+
- A single asynchronous value that might not exist.
|
|
19
|
+
- **`Completable`** -> `suspend fun ...()`
|
|
20
|
+
- An asynchronous operation that completes without a value.
|
|
21
|
+
- **`Observable<T>`** -> `Flow<T>`
|
|
22
|
+
- A cold stream of values.
|
|
23
|
+
- **`Flowable<T>`** -> `Flow<T>`
|
|
24
|
+
- Coroutines Flow natively handles backpressure.
|
|
25
|
+
|
|
26
|
+
### 2. Subjects to Hot Flows
|
|
27
|
+
- **`PublishSubject<T>`** -> `MutableSharedFlow<T>`
|
|
28
|
+
- Broadcasts events to multiple subscribers. Use `MutableSharedFlow(extraBufferCapacity = ...)` if buffering is needed.
|
|
29
|
+
- **`BehaviorSubject<T>`** -> `MutableStateFlow<T>`
|
|
30
|
+
- Holds state and emits the current/latest value to new subscribers. Requires an initial value.
|
|
31
|
+
- **`ReplaySubject<T>`** -> `MutableSharedFlow<T>(replay = N)`
|
|
32
|
+
- Replays the last N emitted values to new subscribers.
|
|
33
|
+
|
|
34
|
+
### 3. Schedulers to Dispatchers
|
|
35
|
+
- **`Schedulers.io()`** -> `Dispatchers.IO`
|
|
36
|
+
- **`Schedulers.computation()`** -> `Dispatchers.Default`
|
|
37
|
+
- **`AndroidSchedulers.mainThread()`** -> `Dispatchers.Main`
|
|
38
|
+
- *Context Switching*: `subscribeOn` and `observeOn` are typically replaced by `withContext(Dispatcher)` or `flowOn(Dispatcher)` for Flows.
|
|
39
|
+
|
|
40
|
+
### 4. Operators
|
|
41
|
+
- **`map`** -> `map`
|
|
42
|
+
- **`filter`** -> `filter`
|
|
43
|
+
- **`flatMap`** -> `flatMapMerge` (concurrent) or `flatMapConcat` (sequential)
|
|
44
|
+
- **`switchMap`** -> `flatMapLatest`
|
|
45
|
+
- **`doOnNext` / `doOnSuccess`** -> `onEach`
|
|
46
|
+
- **`onErrorReturn` / `onErrorResumeNext`** -> `catch { emit(...) }`
|
|
47
|
+
- **`startWith`** -> `onStart { emit(...) }`
|
|
48
|
+
- **`combineLatest`** -> `combine`
|
|
49
|
+
- **`zip`** -> `zip`
|
|
50
|
+
- **`delay`** -> `delay` (suspend function) or `onEach { delay(...) }`
|
|
51
|
+
|
|
52
|
+
### 5. Execution and Lifecycle
|
|
53
|
+
- **`subscribe()`** -> `collect {}` (for Flows) or direct invocation (for suspend functions) inside a `CoroutineScope`.
|
|
54
|
+
- **`Disposable.dispose()`** -> `Job.cancel()`
|
|
55
|
+
- **`CompositeDisposable.clear()`** -> Cancel the parent `CoroutineScope` or `Job`.
|
|
56
|
+
|
|
57
|
+
## Execution Steps
|
|
58
|
+
|
|
59
|
+
1. **Analyze the RxJava Chain**: Identify the source type (Single, Observable, etc.), operators used, and where the subscription happens.
|
|
60
|
+
2. **Convert the Source**: Change the return type in the repository or data source layer first. Convert to `suspend` functions for one-shot operations, and `Flow` for streams.
|
|
61
|
+
3. **Rewrite Operators**: Translate the RxJava operators to their Flow or Coroutine equivalents. Note that many RxJava operators can simply be replaced by standard Kotlin collection/sequence operations inside a `map` or `onEach` block.
|
|
62
|
+
4. **Update the Subscription**: Replace `.subscribe(...)` with `launch { ... }` and `.collect { ... }` in the ViewModel or Presenter. Ensure the launch is tied to the correct lifecycle scope (e.g., `viewModelScope`).
|
|
63
|
+
5. **Handle Errors**: Replace `onError` blocks with `try/catch` around suspend functions, or `.catch { }` operators on Flows.
|
|
64
|
+
6. **Handle Threading**: Remove `.subscribeOn()` and `.observeOn()`. Use `withContext` where necessary, or `.flowOn()` to change the context of the upstream flow.
|
|
65
|
+
|
|
66
|
+
### Example Transformation
|
|
67
|
+
|
|
68
|
+
**RxJava:**
|
|
69
|
+
```kotlin
|
|
70
|
+
fun getUser(id: String): Single<User> { ... }
|
|
71
|
+
|
|
72
|
+
disposable.add(
|
|
73
|
+
getUser("123")
|
|
74
|
+
.subscribeOn(Schedulers.io())
|
|
75
|
+
.observeOn(AndroidSchedulers.mainThread())
|
|
76
|
+
.subscribe({ user ->
|
|
77
|
+
view.showUser(user)
|
|
78
|
+
}, { error ->
|
|
79
|
+
view.showError(error)
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Coroutines/Flow:**
|
|
85
|
+
```kotlin
|
|
86
|
+
suspend fun getUser(id: String): User { ... } // Internally uses withContext(Dispatchers.IO) if needed
|
|
87
|
+
|
|
88
|
+
viewModelScope.launch {
|
|
89
|
+
try {
|
|
90
|
+
val user = getUser("123")
|
|
91
|
+
view.showUser(user)
|
|
92
|
+
} catch (e: Exception) {
|
|
93
|
+
view.showError(e)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Best Practices
|
|
99
|
+
- **Favor Suspend Functions:** Default to `suspend` functions instead of `Flow` unless you actually have a stream of multiple values over time. `Single` and `Completable` almost always become `suspend` functions.
|
|
100
|
+
- **State Handling:** Use `StateFlow` in ViewModels to expose state to the UI instead of `BehaviorSubject` or `LiveData`.
|
|
101
|
+
- **Lifecycle Awareness:** Use `repeatOnLifecycle` or `flowWithLifecycle` in the UI layer when collecting Flows to avoid background work when the view is not visible.
|