|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project |
| 6 | + |
| 7 | +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. |
| 8 | + |
| 9 | +The repository contains **two Gradle modules**: |
| 10 | +- `:library` — the published library (namespace `com.chad.library.adapter4`). This is the artifact. |
| 11 | +- `:app` — the demo application that exercises every library feature (`com.chad.baserecyclerviewadapterhelper`). `demo/` holds a prebuilt APK only. |
| 12 | + |
| 13 | +## Build & Toolchain |
| 14 | + |
| 15 | +Gradle with Kotlin DSL (`settings.gradle`, `build.gradle.kts`, `gradle/libs.versions.toml`). Toolchain and SDK versions are pinned per module: |
| 16 | + |
| 17 | +- **JDK 17** toolchain for both modules (CI uses temurin 17). |
| 18 | +- `: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. |
| 19 | +- `:app` — `compileSdk/targetSdk = 36`, `minSdk = 23`, uses viewBinding + dataBinding, Moshi (KSP codegen). All third-party demo deps live here, never in `:library`. |
| 20 | + |
| 21 | +Common commands (run from repo root): |
| 22 | + |
| 23 | +```bash |
| 24 | +./gradlew :library:compileDebugKotlin # what CI runs — fastest library sanity check |
| 25 | +./gradlew :library:assembleRelease # build the AAR |
| 26 | +./gradlew :app:assembleDebug # build the demo APK |
| 27 | +./gradlew clean |
| 28 | +``` |
| 29 | + |
| 30 | +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. |
| 31 | + |
| 32 | +### Publishing / versioning |
| 33 | +- 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. |
| 34 | +- 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). |
| 35 | +- ProGuard consumer rules ship via `consumerProguardFiles("proguard-rules.pro")` in `:library`, so consumers auto-import them; the file itself is mostly a placeholder. |
| 36 | + |
| 37 | +## Library architecture |
| 38 | + |
| 39 | +Everything is under `com.chad.library.adapter4`. The design centers on one abstract base plus adapter composition via `ConcatAdapter`. |
| 40 | + |
| 41 | +### `BaseQuickAdapter<T, VH>` (the base class) |
| 42 | +`BaseQuickAdapter.kt` is the foundation for all adapters. Two things define it: |
| 43 | + |
| 44 | +1. **Two data modes**, decided at construction by whether a `DiffUtil.ItemCallback<T>`/`AsyncDifferConfig<T>` is supplied: |
| 45 | + - *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. |
| 46 | + - *Plain mode* (`mDiffer == null`) — backs `items` with a plain `List<T>` and calls the corresponding `notifyItem*` directly. |
| 47 | + Every mutating method branches on `mDiffer == null`; when touching one, update **both** branches. |
| 48 | + |
| 49 | +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. |
| 50 | + |
| 51 | +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. |
| 52 | + |
| 53 | +### Adapter variants (all extend `BaseQuickAdapter`) |
| 54 | +- **`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. |
| 55 | +- **`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. |
| 56 | +- **`BaseSingleItemAdapter<T, VH>`** — exactly one item (headers/footers). All list mutation methods throw; use `item`/`setItem()` only. |
| 57 | +- **`BaseDifferAdapter`** — deprecated; `BaseQuickAdapter` now subsumes it. |
| 58 | + |
| 59 | +### Composition: `QuickAdapterHelper` |
| 60 | +`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. |
| 61 | + |
| 62 | +### Load more (`loadState/`) |
| 63 | +- `LoadState` — sealed type: `None`, `NotLoading(endOfPaginationReached)`, `Loading`, `Error`. |
| 64 | +- `LoadStateAdapter<VH>` — base for a load-more adapter; toggles its single item on/off via `displayLoadStateAsItem()`. |
| 65 | +- `TrailingLoadStateAdapter` (tail) / `LeadingLoadStateAdapter` (head), each with a `Default…` implementation. Trailing supports `isAutoLoadMore`, `preloadSize`, and `checkDisableLoadMoreIfNotFullPage()`. |
| 66 | + |
| 67 | +### Supporting utilities |
| 68 | +- `viewholder/QuickViewHolder` — convenience `ViewHolder` with cached `findViewById` and chained setters (`setText`, `setVisible`, …). |
| 69 | +- `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. |
| 70 | +- `dragswipe/QuickDragAndSwipe` + `DragSwipeExt.kt` — drag-and-swipe on top of `ItemTouchHelper`. |
| 71 | +- `animation/*` — `ItemAnimator` implementations (`AlphaIn`, `ScaleIn`, `SlideIn{Left,Right,Bottom}`). |
| 72 | +- `util/AdapterUtils.kt` — `ViewGroup.getItemView(layoutResId)` and `ViewHolder.asStaggeredGridFullSpan()`. |
| 73 | + |
| 74 | +### Internal resource IDs |
| 75 | +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`. |
| 76 | + |
| 77 | +## Conventions |
| 78 | + |
| 79 | +- **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. |
| 80 | +- **Builder/`apply` chaining.** Setters in `BaseQuickAdapter` and `QuickAdapterHelper.Builder` return `apply`/the builder for fluent config. |
| 81 | +- Keep `:library` dependency-free of UI libs — it should only depend on AndroidX `annotation`/`recyclerview` (plus `compileOnly` databinding). Put demo-only dependencies in `:app`. |
0 commit comments