Review Android code changes after implementation to catch crash risks, boundary-condition bugs, and behavioral regressions before commit or merge. Use when asked to inspect staged changes after git add ., review current modified code, review a branch diff, or review a specific commit-id for issues such as null/empty handling, index bounds, lifecycle problems, threading mistakes, memory leaks, ProGuard/R8 shrinking, process death, permission gating, and new crash paths. Trigger examples include code review after coding, 检查当前修改代码, 检查指定 commit-id, 边界条件检查, 崩溃风险检查, 内存泄漏检查, 回归检查, and review staged changes for Android crash risks.
Use this skill after code is written to perform a risk-focused review of Android changes.
Supports staged changes, working tree, branch diff, or a specific commit.
Prioritize runtime safety, Android lifecycle correctness, and regression risk over style-only comments.
Review Scope
Choose the review source first:
Staged changes (preferred for "current changes")
User has already run git add .
Review with git diff --cached
Best for pre-commit safety checks
Working tree changes (fallback)
If changes are not staged
Review with git diff
Clearly state that unstaged changes can still change during review
Branch diff (for PR / feature branch review)
User wants to review all changes since branching from base
Review with git diff <base-branch>...HEAD
Best for PR review before merge
Specific commit
User provides commit hash/id
Review with git show --stat --patch <commit-id>
Best for regression auditing or post-merge incident analysis
git show <commit-id> -- app/src/main/java/.../TargetFile.kt
Review Workflow
Confirm scope
Staged diff, working tree diff, branch diff, or specific commit-id
If commit review, confirm exact hash when ambiguous
Load the diff before reading full files
Start from --stat to see file spread and risk areas
If diff exceeds 30 files or 600 lines, triage by risk: prioritize lifecycle/state/data files over utility/resource files; explicitly state which files were skipped
Then inspect patch hunks for changed conditions, null checks, thread/lifecycle usage
Review for runtime safety and regressions (highest priority first)
Crash paths and boundary conditions
ANR / main-thread blocking risk
Memory and resource leaks
Behavioral regressions
For each Android component type touched in the diff (Activity, Fragment, ViewModel, Compose, RecyclerView, Room, etc.), apply the corresponding hotspot section below
Read surrounding code only where needed
Expand to nearby functions/classes when a patch changes control flow, state, lifecycle, or async behavior
Report findings ordered by severity
Include file/line references
Explain why it can crash/regress and a concrete trigger scenario
Risk Checklist (Android-Focused)
Crash / Exception Risks
Check whether the change can introduce new crash paths:
Nullability mismatches (!!, platform types, nullable API response fields)
@Module binding removed but consumer still has @Inject for it → compile passes, runtime crash
@Singleton applied to a component that depends on Activity context → scope leak
@ActivityRetainedScoped vs @ViewModelScoped confusion causing ViewModel outliving or underliving expected scope
@InstallIn(SingletonComponent::class) on a module that should be per-Activity or per-Fragment
Navigation Safe Args type change in one module but consuming module has stale generated class until clean build
Gradle api → implementation change in a library module silently breaks consuming module compile without visible diff in app module
ProGuard / R8 Shrinking
Release-build-only crashes — must check whenever serialization, reflection, or Parcelable is touched:
Classes used via Class.forName() or reflection without @Keep or keep rule → ClassNotFoundException in release only
Kotlin data class used as JSON deserialization target (Gson/Moshi/kotlinx.serialization) where fields have no @SerializedName → obfuscated names → silent null fields
Enum values referenced by name in serialized data that are renamed by R8
@JsonAdapter or custom TypeAdapter registered by class type that is renamed
Parcelable in inner/anonymous class not surviving shrinking
New serializable/reflective class added without updating proguard-rules.pro or consumer-rules.pro
Manifest / Resources / Config
Android integration regressions often land here:
android:exported / intent-filter combinations invalid on newer SDKs
Component names / authorities / actions changed without callers updated
Low: maintainability/test gap that increases future risk
For each finding include
File + line reference
What changed
Why it can crash/regress
Concrete trigger/boundary scenario
Suggested fix direction (brief)
If no findings
State no major issues found in reviewed diff
Mention residual risks (for example: no runtime test executed, no process-death simulation, no release-build ProGuard verification, no device matrix validation)
Apply regression risk checklist (logic drift, state cleanup, return values)
For each Android component type touched (Activity/Fragment/ViewModel/Compose/RecyclerView/Room/Service/etc.), apply corresponding hotspot section
Check memory & resource leak patterns if any resource allocation or lifecycle changes are present
Check DI/multi-module section if Hilt/Dagger annotations or module structure changed
Check ProGuard/R8 section if any serialization, Parcelable, or reflection-based class is added/renamed/removed
Check state restoration risk (process death / onSaveInstanceState) for any state management change
Note whether validation commands (./gradlew) were run or skipped and why
Report findings with file/line references, or explicitly state no findings with residual risk note
1---2name: android-change-review3description: Review Android code changes after implementation to catch crash risks, boundary-condition bugs, and behavioral regressions before commit or merge. Use when asked to inspect staged changes after git add ., review current modified code, review a branch diff, or review a specific commit-id for issues such as null/empty handling, index bounds, lifecycle problems, threading mistakes, memory leaks, ProGuard/R8 shrinking, process death, permission gating, and new crash paths. Trigger examples include code review after coding, 检查当前修改代码, 检查指定 commit-id, 边界条件检查, 崩溃风险检查, 内存泄漏检查, 回归检查, and review staged changes for Android crash risks.4---56# Android Change Review78## Overview910Use this skill after code is written to perform a risk-focused review of Android changes.11Supports staged changes, working tree, branch diff, or a specific commit.12Prioritize runtime safety, Android lifecycle correctness, and regression risk over style-only comments.1314## Review Scope1516Choose the review source first:1718- **Staged changes (preferred for "current changes")**19 - User has already run `git add .`20 - Review with `git diff --cached`21 - Best for pre-commit safety checks2223- **Working tree changes (fallback)**24 - If changes are not staged25 - Review with `git diff`26 - Clearly state that unstaged changes can still change during review2728- **Branch diff (for PR / feature branch review)**29 - User wants to review all changes since branching from base30 - Review with `git diff <base-branch>...HEAD`31 - Best for PR review before merge3233- **Specific commit**34 - User provides commit hash/id35 - Review with `git show --stat --patch <commit-id>`36 - Best for regression auditing or post-merge incident analysis3738## Quick Start3940### A. Review Staged Changes After `git add .`4142```bash43git add .44git diff --cached --stat45git diff --cached46```4748### B. Review Branch Diff (All Changes vs Base)4950```bash51git diff main...HEAD --stat52git diff main...HEAD53```5455### C. Review a Specific Commit5657```bash58git show --stat --patch <commit-id>59```6061Optional narrower review:6263```bash64git show <commit-id> -- app/src/main/java/.../TargetFile.kt65```6667## Review Workflow68691. Confirm scope70 - Staged diff, working tree diff, branch diff, or specific commit-id71 - If commit review, confirm exact hash when ambiguous72732. Load the diff before reading full files74 - Start from `--stat` to see file spread and risk areas75 - If diff exceeds 30 files or 600 lines, triage by risk: prioritize lifecycle/state/data files over utility/resource files; explicitly state which files were skipped76 - Then inspect patch hunks for changed conditions, null checks, thread/lifecycle usage77783. Review for runtime safety and regressions (highest priority first)79 - Crash paths and boundary conditions80 - ANR / main-thread blocking risk81 - Memory and resource leaks82 - Behavioral regressions83 - For each Android component type touched in the diff (Activity, Fragment, ViewModel, Compose, RecyclerView, Room, etc.), apply the corresponding hotspot section below84854. Read surrounding code only where needed86 - Expand to nearby functions/classes when a patch changes control flow, state, lifecycle, or async behavior87885. Report findings ordered by severity89 - Include file/line references90 - Explain why it can crash/regress and a concrete trigger scenario9192## Risk Checklist (Android-Focused)9394### Crash / Exception Risks9596Check whether the change can introduce new crash paths:9798- Nullability mismatches (`!!`, platform types, nullable API response fields)99- Index/position access (`list[index]`, adapter positions, cursor positions)100- Illegal state timing (`FragmentManager` state saved, duplicate navigation, lifecycle race)101- Class cast / type assumptions after refactor102- Background thread touching UI (`View`, `Fragment`, `Activity`)103- Coroutine/Flow callbacks firing after lifecycle end104- Missing permission checks before protected API calls105- Resource/context usage when `Activity`/`Fragment` is detached or destroyed106- Parsing failures (JSON/Int/Long/Enum/date parsing) after format changes — including new backend Enum value not in client `when` expression107- `lateinit` fields accessed before initialization108- `requireContext()` / `requireActivity()` / `requireArguments()` used without lifecycle safety109- Kotlin `by lazy` delegate accessed from multiple threads without `SYNCHRONIZED` mode110- `object` singleton holding `Activity`/`Context` reference (context leak + stale reference)111- `sealed class` + `when` without `else` — new subclass added silently falls through112113### Boundary Conditions114115Validate input and state boundaries, especially when conditions changed:116117- Empty lists / empty strings / null server fields118- Zero, negative, max, overflow-sized values119- First item / last item / single item collections120- Timeout/retry edge behavior121- Duplicate taps / re-entrancy / repeated callbacks122- Configuration changes (rotation) and process recreation123- **Process death**: "Don't keep activities" enabled — does state survive `onSaveInstanceState` → restore?124 - `ViewModel` used where needed? `SavedStateHandle` used for transient UI state?125 - Deep link launched cold without backstack — does destination assume stack exists?126- Feature flags off/on combinations127- Not-logged-in / low-balance / permission denied / network unavailable states128129### Regression Risks130131Look for behavior changes that may not crash but can break flow:132133- Changed `if` conditions or early returns134- Default value changes135- Error handling removed or exceptions swallowed136- Order-of-operations changes (init before validate, async timing changes)137- State reset/cleanup omitted138- Return value semantics changed139- UI visibility or button enabled-state logic drift140- Navigation route/argument changes without matching callers141142## Android Component Hotspots (Extra Focus)143144### Activity / Fragment / DialogFragment145146Check for lifecycle and UI timing mistakes:147148- View binding used after `onDestroyView()` in Fragment149- Observers collecting with Fragment lifecycle instead of `viewLifecycleOwner`150- `childFragmentManager` / navigation operations after state is saved151- `arguments` keys changed but callers still pass old names/types152- Result callbacks not re-registered after configuration change153- Dialog show/dismiss calls racing with lifecycle transitions154155### ViewModel / LiveData / Flow / Coroutines156157Check async state and cancellation behavior:158159- Work launched in wrong scope (`GlobalScope`, unmanaged scope, missing cancellation)160- `viewModelScope`/`lifecycleScope` misuse causing leaks or lost work161- Flow collection without lifecycle awareness162- Duplicate collectors after repeated `onStart` / `onResume`163- State updates from background thread to non-thread-safe objects164- Exceptions in coroutine chains now uncaught after refactor165166### Jetpack Compose (if touched)167168Check Compose-specific runtime/regression risks:169170- `LaunchedEffect` / `DisposableEffect` keys changed and now re-run incorrectly171- Navigation or one-shot events triggered on every recomposition172- `remember` used where `rememberSaveable` is required (state loss regression)173- Collecting flows without lifecycle-aware APIs when needed174- Mutable state updated from background thread175- `derivedStateOf` / state transformations causing stale UI or infinite recomposition loops176177### RecyclerView / Adapter / Paging178179Common crash and edge-case sources:180181- `adapterPosition` / `bindingAdapterPosition` used without `NO_POSITION` guard182- List updates racing with click callbacks183- DiffUtil identity/content rules changed (incorrect item updates)184- Paging load states not handled for empty/error/retry paths185- Item count assumptions break on empty/one-item lists186187### Navigation / Intent / Deep Link188189Check route and argument safety:190191- Destination args changed but call sites not updated192- Nullable extras now assumed non-null193- Deep-link parsing without validation194- Multiple rapid navigations causing duplicate destination pushes195- `PendingIntent` flags missing or incorrect for current targetSdk196197### Permissions / Privacy / OS Restrictions198199Android-specific gating checks:200201- Runtime permission checks removed, moved, or bypassed202- "Denied once" / "Don't ask again" / permanently denied flows not handled203- Background location / notification / media permissions edge cases204- API-level-specific permission behavior not gated (`Build.VERSION.SDK_INT`)205- Feature call still reachable when permission or service is unavailable206207### Services / WorkManager / Background Work208209Check background execution and process/lifecycle resilience:210211- Foreground service start timing/notification requirements broken212- Work constraints changed (network/charging/idle) causing unexpected execution213- Retry/backoff logic removed or changed214- Duplicate scheduled work due to missing unique work policy215- Broadcast/worker code assuming process state or in-memory cache exists216217### Room / Database / Data Layer218219Check schema and data assumptions:220221- DAO query return type nullability changed222- Migration path missing for schema change223- Transaction boundary changed causing partial writes224- Empty query results no longer handled225- Enum/string mapping changes breaking old persisted values226227### Memory & Resource Leaks228229Common sources of OOM crashes and long-term degradation:230231- `Bitmap` not recycled in `onDraw()`, `onBindViewHolder()`, or image callbacks; use `Glide`/`Coil` recycle helpers232- `Cursor` from `ContentResolver` or raw `Room` query not closed in `finally`/`use` block233- `InputStream`/`OutputStream` not closed — check for missing `use {}` block234- `MediaPlayer`, `AudioTrack`, `Camera`/`Camera2` not released in correct lifecycle callback235- `BroadcastReceiver` registered in `onResume()` but unregistered only in `onStop()` → double-registration risk; or registered but never unregistered236- `AnimatorSet`/`ObjectAnimator` holding a `View` reference after detach, preventing GC237- `Handler`/`HandlerThread` kept alive beyond scope via anonymous `Runnable`; use `WeakReference` or cancel in `onDestroy()`238- `object` companion/singleton holding `Activity` or non-application `Context`239- `registerReceiver` without corresponding `unregisterReceiver` in teardown path240241### Dependency Injection / Multi-Module (Hilt / Dagger)242243Check component scoping and binding correctness:244245- `@Module` binding removed but consumer still has `@Inject` for it → compile passes, runtime crash246- `@Singleton` applied to a component that depends on `Activity` context → scope leak247- `@ActivityRetainedScoped` vs `@ViewModelScoped` confusion causing ViewModel outliving or underliving expected scope248- `@InstallIn(SingletonComponent::class)` on a module that should be per-Activity or per-Fragment249- Navigation Safe Args type change in one module but consuming module has stale generated class until clean build250- Gradle `api` → `implementation` change in a library module silently breaks consuming module compile without visible diff in app module251252### ProGuard / R8 Shrinking253254Release-build-only crashes — must check whenever serialization, reflection, or Parcelable is touched:255256- Classes used via `Class.forName()` or reflection without `@Keep` or keep rule → `ClassNotFoundException` in release only257- Kotlin `data class` used as JSON deserialization target (Gson/Moshi/kotlinx.serialization) where fields have no `@SerializedName` → obfuscated names → silent `null` fields258- `Enum` values referenced by name in serialized data that are renamed by R8259- `@JsonAdapter` or custom `TypeAdapter` registered by class type that is renamed260- `Parcelable` in inner/anonymous class not surviving shrinking261- New serializable/reflective class added without updating `proguard-rules.pro` or `consumer-rules.pro`262263### Manifest / Resources / Config264265Android integration regressions often land here:266267- `android:exported` / intent-filter combinations invalid on newer SDKs268- Component names / authorities / actions changed without callers updated269- Resource key/type changes (`string` → `plurals`, formatting placeholders mismatch `%s/%d`)270- Missing localized resource fallback assumptions271- Proguard/R8 keep rules not updated after reflection/serialization changes272273## Android-Specific Diff Heuristics (Fast Triage)274275When the diff is large, prioritize hunks containing these patterns:276277- `!!`, `lateinit`, `requireContext(`, `requireActivity(`, `as `278- `launch {`, `async`, `withContext`, `collect`, `observe`, `postValue`279- `Fragment`, `Activity`, `onCreate`, `onStart`, `onResume`, `onDestroyView`280- `NavController`, `findNavController`, `navigate(`281- `adapterPosition`, `bindingAdapterPosition`, `DiffUtil`282- `Permission`, `requestPermissions`, `ActivityResult`, `registerForActivityResult`283- `WorkManager`, `Worker`, `Service`, `Foreground`284- `Room`, `Migration`, `Parcelable`, `Intent`, `PendingIntent`285- `Bitmap`, `recycle`, `cursor`, `close(`, `release(`, `unregister`286- `@Keep`, `@SerializedName`, `proguard`, `consumer-rules`287- `@Singleton`, `@InstallIn`, `@HiltViewModel`, `@Inject`288- `by lazy`, `object companion`, `object :`289290**Large diff strategy (>30 files or >600 lines):**2912921. Review files by risk tier first:293 - Tier 1 (review first): lifecycle classes, ViewModel, data/repo layer, navigation294 - Tier 2 (review second): adapters, custom views, service/worker classes295 - Tier 3 (review last or skip): utility files, string resources, non-logic config2962. Explicitly state which files were reviewed and which were skipped due to diff size2973. If scope was reduced, recommend a follow-up review on skipped files298299## Severity Decision Framework300301Use these criteria when assigning severity to findings:302303| Severity | Criteria |304|----------|----------|305| **High** | Crash reproducible deterministically on any device or common user path; data corruption; auth/payment flow broken |306| **High** | Silent data loss: state not saved, wrong data persisted, wrong item deleted |307| **Medium** | Crash only under race condition, specific device, or edge-case input; wrong fallback behavior visible to user |308| **Medium** | Regression in business logic that does not crash but produces incorrect output |309| **Low** | Logic error with no immediate user-visible impact; maintainability gap increasing future risk |310| **Low** | Test coverage gap that leaves a crash path unverified |311312Escalate Low → Medium if the finding is in a payment, authentication, or data persistence path.313314## Optional Validation Commands (After Review Findings)315316When useful and available, run targeted checks to increase confidence:317318```bash319# Narrow compile checks (module/task depends on project)320./gradlew :app:compileDebugKotlin321./gradlew :app:compileDebugJavaWithJavac322323# Lint / unit tests (prefer impacted module)324./gradlew :app:lintDebug325./gradlew :app:testDebugUnitTest326```327328Use targeted tasks when the project is large. Report if checks were not run.329330## Commands Reference331332Use these commands depending on scope:333334```bash335# Staged review (preferred after user runs git add .)336git diff --cached --name-only337git diff --cached --stat338git diff --cached339340# Working tree review (if not staged)341git diff --name-only342git diff --stat343git diff344345# Branch / PR review (all changes vs base branch)346git diff main...HEAD --stat347git diff main...HEAD348349# Commit review350git show --name-only --stat <commit-id>351git show --stat --patch <commit-id>352```353354## Output Format (Recommended)355356When reporting review results:3573581. Findings first (severity ordered)359 - `High`: likely crash / data corruption / major regression360 - `Medium`: edge-case breakage, flaky behavior, incorrect fallback361 - `Low`: maintainability/test gap that increases future risk3623632. For each finding include364 - File + line reference365 - What changed366 - Why it can crash/regress367 - Concrete trigger/boundary scenario368 - Suggested fix direction (brief)3693703. If no findings371 - State no major issues found in reviewed diff372 - Mention residual risks (for example: no runtime test executed, no process-death simulation, no release-build ProGuard verification, no device matrix validation)373374## Example Requests375376- "代码写完了,帮我做代码检查,我已经 `git add .` 了,重点看会不会 crash。"377- "请检查当前修改代码的边界条件和回归风险。"378- "我已经 git add . 了,帮我按 Android 生命周期/权限/线程角度做一轮代码检查。"379- "Review my staged changes for Android crash risks."380- "Review this Compose/Fragment change for lifecycle and recomposition regressions."381- "帮我检查 commit `abc1234`,看有没有新的崩溃路径。"382- "Review commit-id for boundary conditions and regressions."383- "帮我检查这个 branch 的所有修改,看有没有内存泄漏和 ProGuard 问题。"384- "Review all changes on this feature branch before PR merge."385386## Checklist387388Before finishing the review:389390- [ ] Confirm review scope (staged / working tree / branch diff / commit-id)391- [ ] Inspect diff patch, not only filenames; apply large-diff triage strategy if needed392- [ ] Apply crash risk checklist (nullability, index, lifecycle, Kotlin traps)393- [ ] Apply boundary conditions checklist (empty/null/zero/process death/config change)394- [ ] Apply regression risk checklist (logic drift, state cleanup, return values)395- [ ] For each Android component type touched (Activity/Fragment/ViewModel/Compose/RecyclerView/Room/Service/etc.), apply corresponding hotspot section396- [ ] Check memory & resource leak patterns if any resource allocation or lifecycle changes are present397- [ ] Check DI/multi-module section if Hilt/Dagger annotations or module structure changed398- [ ] Check ProGuard/R8 section if any serialization, Parcelable, or reflection-based class is added/renamed/removed399- [ ] Check state restoration risk (process death / `onSaveInstanceState`) for any state management change400- [ ] Note whether validation commands (`./gradlew`) were run or skipped and why401- [ ] Report findings with file/line references, or explicitly state no findings with residual risk note
Run npx skillmds@latest add aihip/android-change-review in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Review Android code changes after implementation to catch crash risks, boundary-condition bugs, and behavioral regressions before commit or merge. Use when asked to inspect staged changes after git add ., review current modified code, review a branch diff, or review a specific commit-id for issues such as null/empty handling, index bounds, lifecycle problems, threading mistakes, memory leaks, ProGuard/R8 shrinking, process death, permission gating, and new crash paths. Trigger examples include code review after coding, 检查当前修改代码, 检查指定 commit-id, 边界条件检查, 崩溃风险检查, 内存泄漏检查, 回归检查, and review staged changes for Android crash risks. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: docs only. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
aihip (@aihip) published this skill. Their other Agent Skills are listed on their SkillMD profile.