Agent skills, system prompts, and AI developer rules for CymChad/BaseRecyclerViewAdapterHelper
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project
BRVAH (BaseRecyclerViewAdapterHelper) β a RecyclerView Adapter helper library for Android (current major version: **v4.x**, published as `io.github.cymchad:BaseRecyclerViewAdapterHelper4`). v4 was rewritten to be fully compatible with `ConcatAdapter`, to split functionality into modules, and to support flexible multi-type layouts plus strengthened up/down load-more.
The repository contains **two Gradle modules**:
- `:library` β the published library (namespace `com.chad.library.adapter4`). This is the artifact.
- `:app` β the demo application that exercises every library feature (`com.chad.baserecyclerviewadapterhelper`). `demo/` holds a prebuilt APK only.
## Build & Toolchain
Gradle with Kotlin DSL (`settings.gradle`, `build.gradle.kts`, `gradle/libs.versions.toml`). Toolchain and SDK versions are pinned per module:
- **JDK 17** toolchain for both modules (CI uses temurin 17).
- `:library` β `compileSdk = 35`, `minSdk = 19`, depends only on `androidx.annotation`, `androidx.recyclerview`, and `compileOnly` `databinding-runtime`. No AndroidX app deps β it is a pure library.
- `:app` β `compileSdk/targetSdk = 36`, `minSdk = 23`, uses viewBinding + dataBinding, Moshi (KSP codegen). All third-party demo deps live here, never in `:library`.
Common commands (run from repo root):
```bash
./gradlew :library:compileDebugKotlin # what CI runs β fastest library sanity check
./gradlew :library:assembleRelease # build the AAR
./gradlew :app:assembleDebug # build the demo APK
./gradlew clean
```
There is **no test source set** β there are no unit or instrumented tests in either module. Verify changes by compiling and/or running the demo app.
### Publishing / versioning
- Library version lives in `library/build.gradle.kts` as `val versionName` (currently `4.4.1`). The `:app` `versionName` (`4.3.2`) is independent β update them separately.
- Publishing is configured with `maven-publish` + `signing`. Credentials/signing keys are read from `local.properties` (`signing.keyId`, `signing.password`, `signing.secretKeyRingFile`, `ossrhUsername`, `ossrhPassword`). The active publish repository is the local `$rootDir/Repo` folder (Maven Central upload block is commented out).
- ProGuard consumer rules ship via `consumerProguardFiles("proguard-rules.pro")` in `:library`, so consumers auto-import them; the file itself is mostly a placeholder.
## Library architecture
Everything is under `com.chad.library.adapter4`. The design centers on one abstract base plus adapter composition via `ConcatAdapter`.
### `BaseQuickAdapter<T, VH>` (the base class)
`BaseQuickAdapter.kt` is the foundation for all adapters. Two things define it:
1. **Two data modes**, decided at construction by whether a `DiffUtil.ItemCallback<T>`/`AsyncDifferConfig<T>` is supplied:
- *Diff mode* β backs `items` with `AsyncListDiffer` (async diffing, no jank). Mutating ops (`submitList`, `add`, `set`, `removeAt`, `swap`, `move`, β¦) rebuild a mutable list and re-submit.
- *Plain mode* (`mDiffer == null`) β backs `items` with a plain `List<T>` and calls the corresponding `notifyItem*` directly.
Every mutating method branches on `mDiffer == null`; when touching one, update **both** branches.
2. **Sealed RecyclerView.Adapter overrides.** `getItemCount()`, `getItemViewType()`, `onCreateViewHolder()`, and `onBindViewHolder()` are `final`. Subclasses implement the **protected** variants instead (`onCreateViewHolder(context, parent, viewType)`, `onBindViewHolder(holder, position, item[, payloads])`, `getItemCount(items)`, `getItemViewType(position, list)`). Do not try to override the final ones.
Other base-class responsibilities: optional **state/empty view** (`isStateViewEnable` + `stateView`, shown when `items` is empty via `StateLayoutVH`), item **animations** (`animationEnable` + `itemAnimation`/`setItemAnimation(AnimationType)`), and click listeners (item / item-child by view id, stored in a `SparseArray`). `items` setter is `@Deprecated` at **ERROR level** β use `submitList()` to replace data.
### Adapter variants (all extend `BaseQuickAdapter`)
- **`BaseMultiItemAdapter<T>`** β multi view-type layouts. Register each type with `addItemType(viewType, OnMultiItemAdapterListener)` and decide types via `onItemViewType { position, list -> }`. The listener (or `OnMultiItem` subclass, which grants `adapter`/`context`) provides `onCreate`/`onBind` per type.
- **`BaseNodeAdapter`** β tree/expandable lists. Subclasses implement `getChildNodeList()` and `isInitialOpen()`; `open()`/`close()`/`openOrClose()`/`closeAll()` drive expansion. Open/closed state is tracked by a custom `NodeSet` matched through `isSameNode()` (override for value-based nodes; default is `===`). See the bilingual KDoc on `isSameNode` β it must uniquely identify a node or expand/collapse state leaks across nodes.
- **`BaseSingleItemAdapter<T, VH>`** β exactly one item (headers/footers). All list mutation methods throw; use `item`/`setItem()` only.
- **`BaseDifferAdapter`** β deprecated; `BaseQuickAdapter` now subsumes it.
### Composition: `QuickAdapterHelper`
`QuickAdapterHelper` wraps a content adapter in a `ConcatAdapter` and exposes `helper.adapter` to set on the `RecyclerView`. Layout order: `LeadingLoadStateAdapter` β before-adapters β **content adapter** β after-adapters β `TrailingLoadStateAdapter`. Built via `QuickAdapterHelper.Builder(contentAdapter)` with optional leading/trailing load-more, then `.build()` or `.attachTo(recyclerView)`. This is the canonical way to get header/footer and up/down load-more in v4 β header/footer are separate small adapters prepended/appended, not built-in fields of the base adapter.
### Load more (`loadState/`)
- `LoadState` β sealed type: `None`, `NotLoading(endOfPaginationReached)`, `Loading`, `Error`.
- `LoadStateAdapter<VH>` β base for a load-more adapter; toggles its single item on/off via `displayLoadStateAsItem()`.
- `TrailingLoadStateAdapter` (tail) / `LeadingLoadStateAdapter` (head), each with a `Defaultβ¦` implementation. Trailing supports `isAutoLoadMore`, `preloadSize`, and `checkDisableLoadMoreIfNotFullPage()`.
### Supporting utilities
- `viewholder/QuickViewHolder` β convenience `ViewHolder` with cached `findViewById` and chained setters (`setText`, `setVisible`, β¦).
- `layoutmanager/QuickGridLayoutManager` β `GridLayoutManager` that grants full span to adapters implementing `FullSpanAdapterType`, and to `BaseQuickAdapter` view types for which `isFullSpanItem(type)` is true (the empty/state view is full-span by default). Use it (or your own `SpanSizeLookup`) when an item must span all columns.
- `dragswipe/QuickDragAndSwipe` + `DragSwipeExt.kt` β drag-and-swipe on top of `ItemTouchHelper`.
- `animation/*` β `ItemAnimator` implementations (`AlphaIn`, `ScaleIn`, `SlideIn{Left,Right,Bottom}`).
- `util/AdapterUtils.kt` β `ViewGroup.getItemView(layoutResId)` and `ViewHolder.asStaggeredGridFullSpan()`.
### Internal resource IDs
The library declares IDs in `library/src/main/res/values/ids.xml` (e.g. `BaseQuickAdapter_empty_view`, `BaseQuickAdapter_key_multi`) used for internal view tagging and the empty-view `viewType`. The `EMPTY_VIEW` companion constant points at `R.id.BaseQuickAdapter_empty_view`.
## Conventions
- **Bilingual KDoc.** Public API documentation is written in **both Chinese and English** (Chinese typically first, then English). Match this style when adding or editing public APIs.
- **Builder/`apply` chaining.** Setters in `BaseQuickAdapter` and `QuickAdapterHelper.Builder` return `apply`/the builder for fluent config.
- Keep `:library` dependency-free of UI libs β it should only depend on AndroidX `annotation`/`recyclerview` (plus `compileOnly` databinding). Put demo-only dependencies in `:app`.