feat: power claude templates
This commit is contained in:
3
.claude/commands/build-debug.md
Normal file
3
.claude/commands/build-debug.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
构建项目的 Debug 版本 APK
|
||||||
|
|
||||||
|
./gradlew assembleDebug
|
||||||
3
.claude/commands/build-release.md
Normal file
3
.claude/commands/build-release.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
构建项目的 Release 版本 APK (已签名)
|
||||||
|
|
||||||
|
./gradlew assembleRelease
|
||||||
6
.claude/commands/check-modules.md
Normal file
6
.claude/commands/check-modules.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
显示项目中所有模块的列表和基本信息
|
||||||
|
|
||||||
|
echo "=== 项目模块列表 ===" && \
|
||||||
|
cat settings.gradle | grep "include" && \
|
||||||
|
echo "\n=== 模块目录 ===" && \
|
||||||
|
ls -la | grep "^d" | grep "module_"
|
||||||
3
.claude/commands/clean-build.md
Normal file
3
.claude/commands/clean-build.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
清理构建缓存并重新构建 Debug 版本
|
||||||
|
|
||||||
|
./gradlew clean && ./gradlew assembleDebug
|
||||||
3
.claude/commands/devices.md
Normal file
3
.claude/commands/devices.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
列出所有已连接的 Android 设备和模拟器
|
||||||
|
|
||||||
|
adb devices -l
|
||||||
3
.claude/commands/install.md
Normal file
3
.claude/commands/install.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
构建并安装 Debug 版本到连接的 Android 设备或模拟器
|
||||||
|
|
||||||
|
./gradlew installDebug
|
||||||
3
.claude/commands/lint.md
Normal file
3
.claude/commands/lint.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
运行 Android Lint 代码质量检查
|
||||||
|
|
||||||
|
./gradlew lint
|
||||||
3
.claude/commands/logs.md
Normal file
3
.claude/commands/logs.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
实时查看应用日志 (过滤应用包名)
|
||||||
|
|
||||||
|
adb logcat | grep "com.lukouguoji.aerologic"
|
||||||
@@ -24,7 +24,14 @@
|
|||||||
"WebSearch",
|
"WebSearch",
|
||||||
"Bash(chmod:*)",
|
"Bash(chmod:*)",
|
||||||
"Bash(xargs ls:*)",
|
"Bash(xargs ls:*)",
|
||||||
"Bash(xargs rm -rf)"
|
"Bash(xargs rm -rf)",
|
||||||
|
"Bash(for module in module_gnc module_gnj module_gjc module_gjj module_hangban module_cargo module_mit module_p Printer MPChartLib)",
|
||||||
|
"Bash(do echo '=== $module ===' ls -la /Users/kid/Development/Fusion/Projects/aerologic-app/$module/)",
|
||||||
|
"Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app log --oneline)",
|
||||||
|
"Bash(git -C /Users/kid/Development/Fusion/Projects/aerologic-app branch -a)",
|
||||||
|
"Bash(adb:*)",
|
||||||
|
"Bash(emulator:*)",
|
||||||
|
"Bash(logcat:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
101
CHANGELOG.md
Normal file
101
CHANGELOG.md
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# 版本变更日志 (Changelog)
|
||||||
|
|
||||||
|
本文档记录 AirLogistics 项目的所有重要变更。
|
||||||
|
|
||||||
|
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||||
|
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||||
|
|
||||||
|
## [1.8.4] - 2024-12-02
|
||||||
|
|
||||||
|
### 新增 (Added)
|
||||||
|
- 完善 Claude Code 配置,添加 Android 开发权限
|
||||||
|
- 创建 8 个快捷命令 (/build-debug, /install, /logs 等)
|
||||||
|
- 定制 CLAUDE.md 为 Android 项目专用开发指南
|
||||||
|
- 添加 CONTRIBUTING.md 贡献指南文档
|
||||||
|
- 添加 CHANGELOG.md 版本变更日志
|
||||||
|
|
||||||
|
### 改进 (Changed)
|
||||||
|
- 优化首页菜单交互体验
|
||||||
|
- 改进 UI 界面显示效果
|
||||||
|
|
||||||
|
### 技术栈
|
||||||
|
- Kotlin 1.6.21
|
||||||
|
- Android Gradle Plugin 7.2.0
|
||||||
|
- Gradle 7.3.3
|
||||||
|
- minSdk 24, targetSdk 30, compileSdk 31
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [1.8.x] - 之前版本
|
||||||
|
|
||||||
|
### 主要功能
|
||||||
|
- 国内出港业务模块 (货物收运、复磅称重、转运管理、出库装机)
|
||||||
|
- 国内进港业务模块 (舱单管理、卸机入库、出库提货、移库管理)
|
||||||
|
- 国际出港业务模块 (国际货物收运、板箱组装、ULD容器管理)
|
||||||
|
- 国际进港业务模块 (国际舱单管理、报文解析、理货管理)
|
||||||
|
- 航班管理模块 (航班查询、航班统计)
|
||||||
|
- 货物追踪模块 (货物状态追踪、运输日志)
|
||||||
|
- 监装监卸模块 (监装监卸管理)
|
||||||
|
- PDA功能模块 (PDA专用功能)
|
||||||
|
- 蓝牙打印模块 (佳博打印机集成)
|
||||||
|
|
||||||
|
### 核心架构
|
||||||
|
- MVVM 架构模式
|
||||||
|
- 组件化模块设计 (11个业务模块 + 1个基础库)
|
||||||
|
- DataBinding 双向绑定
|
||||||
|
- Kotlin Coroutines + Flow 异步处理
|
||||||
|
- ARouter 模块间通信
|
||||||
|
- Retrofit + OkHttp 网络请求
|
||||||
|
- Glide 图片加载
|
||||||
|
- MPAndroidChart 图表展示
|
||||||
|
|
||||||
|
### 开发基础设施
|
||||||
|
- BaseActivity/BaseBindingActivity 基类
|
||||||
|
- BaseViewModel/BasePageViewModel 基类
|
||||||
|
- CommonAdapter + BaseViewHolder 列表适配
|
||||||
|
- PadSearchLayout/PadDataLayout 自定义组件
|
||||||
|
- 完整的 Kotlin 扩展函数库
|
||||||
|
- DataBinding 适配器集合
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 版本说明
|
||||||
|
|
||||||
|
### 版本号规则
|
||||||
|
- **Major.Minor.Patch** (例: 1.8.4)
|
||||||
|
- **Major**: 重大架构变更或不兼容的 API 修改
|
||||||
|
- **Minor**: 新功能添加,向下兼容
|
||||||
|
- **Patch**: Bug 修复和小的改进
|
||||||
|
|
||||||
|
### 变更类型
|
||||||
|
- **Added**: 新增功能
|
||||||
|
- **Changed**: 功能改进或变更
|
||||||
|
- **Deprecated**: 即将废弃的功能
|
||||||
|
- **Removed**: 已移除的功能
|
||||||
|
- **Fixed**: Bug 修复
|
||||||
|
- **Security**: 安全性修复
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 未来计划
|
||||||
|
|
||||||
|
### 待开发功能
|
||||||
|
- [ ] 优化数据同步机制
|
||||||
|
- [ ] 增强离线模式支持
|
||||||
|
- [ ] 改进用户权限管理
|
||||||
|
- [ ] 优化蓝牙打印稳定性
|
||||||
|
- [ ] 添加数据导出功能
|
||||||
|
- [ ] 性能监控和分析
|
||||||
|
|
||||||
|
### 技术改进
|
||||||
|
- [ ] 升级到 Kotlin 2.0
|
||||||
|
- [ ] 迁移到 Jetpack Compose
|
||||||
|
- [ ] 优化构建速度
|
||||||
|
- [ ] 完善单元测试覆盖
|
||||||
|
- [ ] 添加 UI 自动化测试
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**维护**: 本文档应在每次版本发布时更新。
|
||||||
|
**负责人**: 项目维护团队
|
||||||
|
**最后更新**: 2024-12-02
|
||||||
646
CLAUDE.md
646
CLAUDE.md
@@ -1,41 +1,207 @@
|
|||||||
# CLAUDE.md
|
# CLAUDE.md
|
||||||
|
|
||||||
项目开发指南 - 航空物流App
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
## 项目概述
|
## Android 项目特定说明
|
||||||
|
|
||||||
**AirLogistics** - Android原生应用,航空物流全流程管理
|
### 项目概况
|
||||||
|
|
||||||
- **包名**: com.lukouguoji.aerologic
|
**项目名称**: AirLogistics - 航空物流信息管理系统
|
||||||
- **版本**: 1.7.9 (API 24-30)
|
**项目类型**: Android 原生应用
|
||||||
- **架构**: MVVM + 组件化 + Kotlin + DataBinding
|
**架构模式**: MVVM + 组件化
|
||||||
- **屏幕**: 横屏 1152dp × 720dp
|
**开发语言**: Kotlin 1.6.21 + Java
|
||||||
|
**当前版本**: 1.8.4 (versionCode 84)
|
||||||
|
|
||||||
## 快速构建
|
**SDK 版本要求**:
|
||||||
|
- minSdkVersion: 24 (Android 7.0)
|
||||||
|
- targetSdkVersion: 30 (Android 10)
|
||||||
|
- compileSdkVersion: 31
|
||||||
|
|
||||||
|
### 核心架构
|
||||||
|
|
||||||
|
#### MVVM 基类体系
|
||||||
|
- **BaseActivity**: 提供协程支持、Loading管理、扫码功能、键盘控制
|
||||||
|
- **BaseBindingActivity**: DataBinding自动绑定、ViewModel生命周期管理
|
||||||
|
- **BaseViewModel**: Loading管理、Activity结果处理
|
||||||
|
- **BasePageViewModel**: 分页列表专用,集成PageModel自动处理分页
|
||||||
|
- **CommonAdapter + BaseViewHolder**: 统一列表适配器封装
|
||||||
|
|
||||||
|
#### 组件化模块划分
|
||||||
|
- **app/**: 应用壳层,整合所有业务模块
|
||||||
|
- **module_base/**: 核心基础库(MVVM基类、网络框架、UI组件)
|
||||||
|
- **module_gnc/**: 国内出港业务模块
|
||||||
|
- **module_gnj/**: 国内进港业务模块
|
||||||
|
- **module_gjc/**: 国际出港业务模块
|
||||||
|
- **module_gjj/**: 国际进港业务模块
|
||||||
|
- **module_hangban/**: 航班管理模块
|
||||||
|
- **module_cargo/**: 货物追踪模块
|
||||||
|
- **module_mit/**: 监装监卸管理模块
|
||||||
|
- **module_p/**: PDA专用功能模块
|
||||||
|
- **Printer/**: 蓝牙打印模块
|
||||||
|
- **MPChartLib/**: 图表库模块
|
||||||
|
|
||||||
|
#### 模块间通信
|
||||||
|
- **路由**: ARouter 1.5.2 实现模块间页面跳转
|
||||||
|
- **事件总线**: FlowBus(基于Flow) + EventBus 3.1.1
|
||||||
|
- **依赖注入**: 基于ServiceLoader的服务发现机制
|
||||||
|
|
||||||
|
#### 网络请求框架
|
||||||
|
- **技术栈**: Retrofit 2.6.1 + OkHttp 3.12.12 + Kotlin Coroutines
|
||||||
|
- **扩展函数**:
|
||||||
|
- `launchCollect`: 无Loading的后台请求
|
||||||
|
- `launchLoadingCollect`: 带Loading的关键操作
|
||||||
|
- `toRequestBody`: Map/Bean自动转JSON
|
||||||
|
- **拦截器**: 自动添加Token、时间戳,统一错误处理
|
||||||
|
|
||||||
|
### 关键目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
aerologic-app/
|
||||||
|
├── app/src/main/java/com/lukouguoji/aerologic/
|
||||||
|
│ ├── ui/viewModel/ # ViewModel文件
|
||||||
|
│ ├── ui/fragment/ # Fragment文件 (HomeFragment, MineFragment等)
|
||||||
|
│ └── page/ # 业务页面
|
||||||
|
├── module_base/src/main/java/com/lukouguoji/module_base/
|
||||||
|
│ ├── BaseActivity.kt # 基础Activity类
|
||||||
|
│ ├── BaseFragment.kt # 基础Fragment类
|
||||||
|
│ ├── bean/ # 数据模型 (BaseResultBean, BaseListBean)
|
||||||
|
│ ├── service/viewModel/ # ViewModel层
|
||||||
|
│ ├── ui/page/ # UI页面
|
||||||
|
│ ├── ui/weight/ # 自定义UI组件 (PadSearchLayout, PadDataLayout)
|
||||||
|
│ ├── http/ # 网络请求框架
|
||||||
|
│ └── ktx/ # Kotlin扩展函数
|
||||||
|
├── module_gnc/src/main/ # 国内出港业务代码
|
||||||
|
├── module_gnj/src/main/ # 国内进港业务代码
|
||||||
|
└── 其他业务模块...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开发规范
|
||||||
|
|
||||||
|
#### 命名约定
|
||||||
|
- **Activity**: `XxxActivity` (例: `LoginActivity`)
|
||||||
|
- **Fragment**: `XxxFragment` (例: `HomeFragment`)
|
||||||
|
- **ViewModel**: `XxxViewModel` (例: `LoginViewModel`)
|
||||||
|
- **Adapter**: `XxxAdapter` (例: `CargoListAdapter`)
|
||||||
|
- **ViewHolder**: `XxxViewHolder` (例: `CargoItemViewHolder`)
|
||||||
|
- **Layout文件**: `activity_xxx.xml`, `fragment_xxx.xml`, `item_xxx.xml`
|
||||||
|
|
||||||
|
#### 文件组织规范
|
||||||
|
- 业务页面放在对应模块的 `ui/page/` 目录下
|
||||||
|
- ViewModel放在 `service/viewModel/` 目录下
|
||||||
|
- 数据模型放在 `bean/` 目录下
|
||||||
|
- 适配器放在 `adapter/` 目录下
|
||||||
|
|
||||||
|
#### DataBinding 使用要点
|
||||||
|
- 布局文件使用 `<layout>` 标签包裹
|
||||||
|
- 定义 `<variable>` 绑定 ViewModel
|
||||||
|
- 使用 `@{}` 表达式进行数据绑定
|
||||||
|
- Activity/Fragment 中使用 `DataBindingUtil` 或自动生成的 Binding 类
|
||||||
|
|
||||||
|
#### 协程使用规范
|
||||||
|
- 在 ViewModel 中使用 `viewModelScope` 启动协程
|
||||||
|
- 网络请求使用 `launchCollect` 或 `launchLoadingCollect` 扩展函数
|
||||||
|
- Flow 用于响应式数据流处理
|
||||||
|
- 使用 `withContext(Dispatchers.IO)` 进行IO操作
|
||||||
|
|
||||||
|
### 常用构建命令
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./gradlew assembleDebug # 构建Debug版本
|
# 清理构建缓存
|
||||||
./gradlew clean # 清理构建
|
./gradlew clean
|
||||||
|
|
||||||
|
# 构建 Debug APK
|
||||||
|
./gradlew assembleDebug
|
||||||
|
|
||||||
|
# 构建 Release APK (已签名)
|
||||||
|
./gradlew assembleRelease
|
||||||
|
|
||||||
|
# 安装到设备
|
||||||
|
./gradlew installDebug
|
||||||
|
|
||||||
|
# 运行 Lint 检查
|
||||||
|
./gradlew lint
|
||||||
|
|
||||||
|
# 查看已连接设备
|
||||||
|
adb devices -l
|
||||||
|
|
||||||
|
# 查看应用日志
|
||||||
|
adb logcat | grep "com.lukouguoji.aerologic"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 核心架构
|
### 快捷命令
|
||||||
|
|
||||||
### MVVM层级
|
项目已配置以下快捷命令 (在 `.claude/commands/` 目录):
|
||||||
|
- `/build-debug` - 构建 Debug APK
|
||||||
|
- `/build-release` - 构建 Release APK
|
||||||
|
- `/install` - 安装到设备
|
||||||
|
- `/clean-build` - 清理并构建
|
||||||
|
- `/check-modules` - 检查所有模块
|
||||||
|
- `/lint` - 运行代码检查
|
||||||
|
- `/devices` - 列出已连接设备
|
||||||
|
- `/logs` - 查看应用日志
|
||||||
|
|
||||||
```
|
### 组件化开发模式
|
||||||
Activity → BaseBindingActivity → ViewModel → BaseViewModel/BasePageViewModel → API
|
|
||||||
|
项目支持模块独立运行调试:
|
||||||
|
|
||||||
|
1. 编辑 `gradle.properties`
|
||||||
|
2. 设置 `isBuildModule=true` (独立模式) 或 `false` (集成模式)
|
||||||
|
3. Sync项目并运行对应模块
|
||||||
|
|
||||||
|
**注意**: 独立模式下,各模块作为独立应用运行;集成模式下,所有模块整合到app壳层。
|
||||||
|
|
||||||
|
### 环境配置
|
||||||
|
|
||||||
|
#### 开发环境要求
|
||||||
|
- **IDE**: Android Studio Arctic Fox (2020.3.1) 或更高版本
|
||||||
|
- **JDK**: 1.8
|
||||||
|
- **Gradle**: 7.3.3
|
||||||
|
- **Kotlin**: 1.6.21
|
||||||
|
|
||||||
|
#### 服务器配置
|
||||||
|
- **配置文件**: `module_base/src/main/res/values/strings.xml`
|
||||||
|
- **主服务器**: `system_url_inner`
|
||||||
|
- **地磅服务器**: `weight_url`
|
||||||
|
- **运行时**: 可通过 SharedPreferences 动态修改IP地址
|
||||||
|
|
||||||
|
#### 签名配置
|
||||||
|
- **KeyStore**: `key.jks` (项目根目录)
|
||||||
|
- **Store密码**: `123321`
|
||||||
|
- **Key密码**: `123321`
|
||||||
|
- **别名**: `key`
|
||||||
|
|
||||||
|
### 常见问题解决
|
||||||
|
|
||||||
|
#### 依赖下载失败
|
||||||
|
1. 检查网络连接
|
||||||
|
2. 使用阿里云Maven镜像 (已在 build.gradle 中配置)
|
||||||
|
3. 如需手动配置 Gradle,参考 README.md 中的依赖配置章节
|
||||||
|
|
||||||
|
#### 模块编译错误
|
||||||
|
1. 执行 `./gradlew clean`
|
||||||
|
2. 检查 `gradle.properties` 中的 `isBuildModule` 设置
|
||||||
|
3. Sync Project with Gradle Files
|
||||||
|
|
||||||
|
#### ADB 连接问题
|
||||||
|
```bash
|
||||||
|
# 重启 ADB 服务
|
||||||
|
adb kill-server && adb start-server
|
||||||
|
|
||||||
|
# 查看设备连接状态
|
||||||
|
adb devices -l
|
||||||
|
|
||||||
|
# 无线调试 (Android 11+)
|
||||||
|
adb pair <IP>:<PORT>
|
||||||
|
adb connect <IP>:<PORT>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 关键基类
|
---
|
||||||
|
|
||||||
- **BaseBindingActivity**: DataBinding + ViewModel自动绑定
|
## 详细开发指南
|
||||||
- **BaseViewModel**: Loading管理、协程支持
|
|
||||||
- **BasePageViewModel**: 分页列表(含PageModel)
|
|
||||||
- **CommonAdapter + BaseViewHolder**: 列表适配器
|
|
||||||
- **PadSearchLayout**: 搜索区域输入控件
|
|
||||||
- **PadDataLayout**: 数据展示/编辑控件
|
|
||||||
|
|
||||||
### 标准Activity模板
|
### 标准代码模板
|
||||||
|
|
||||||
|
#### Activity 模板
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@Route(path = ARouterConstants.ACTIVITY_URL_XXX)
|
@Route(path = ARouterConstants.ACTIVITY_URL_XXX)
|
||||||
@@ -51,7 +217,7 @@ class XxxActivity : BaseBindingActivity<ActivityXxxBinding, XxxViewModel>() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 标准ViewModel模板
|
#### ViewModel 模板
|
||||||
|
|
||||||
**列表页 ViewModel:**
|
**列表页 ViewModel:**
|
||||||
|
|
||||||
@@ -139,83 +305,27 @@ class XxxAddViewModel : BaseViewModel() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 网络请求
|
### DataBinding + LiveData 核心知识
|
||||||
|
|
||||||
### 请求方法
|
#### 最关键的设置 (最常见错误)
|
||||||
|
|
||||||
```kotlin
|
**必须在 Activity 中设置 lifecycleOwner,否则 XML 中的 LiveData 不会自动更新 UI!**
|
||||||
// 带Loading请求
|
|
||||||
launchLoadingCollect({ NetApply.api.saveXxx(params) }) {
|
|
||||||
onSuccess = { /* 成功处理 */ }
|
|
||||||
onFailed = { code, msg -> /* 失败处理 */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 无Loading请求(后台刷新)
|
|
||||||
launchCollect({ NetApply.api.getXxx() }) {
|
|
||||||
onSuccess = { /* 成功处理 */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数转换
|
|
||||||
val params = mapOf("key" to "value").toRequestBody(removeEmptyOrNull = true)
|
|
||||||
```
|
|
||||||
|
|
||||||
### API接口定义
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
// 位置: module_base/.../http/net/Api.kt
|
|
||||||
@POST("api/xxx/list")
|
|
||||||
suspend fun getXxxList(@Body data: RequestBody): BaseListBean<XxxBean>
|
|
||||||
|
|
||||||
@POST("api/xxx/details")
|
|
||||||
suspend fun getXxxDetails(@Query("id") id: String): BaseResultBean<XxxBean>
|
|
||||||
|
|
||||||
@POST("api/xxx/save")
|
|
||||||
suspend fun saveXxx(@Body data: RequestBody): BaseResultBean<SimpleResultBean>
|
|
||||||
```
|
|
||||||
|
|
||||||
## DataBinding + LiveData + ViewModel 核心知识
|
|
||||||
|
|
||||||
### 🎯 最关键的设置(最常见错误)
|
|
||||||
|
|
||||||
**必须在 Activity 中设置 lifecycleOwner,否则 XML 中的 LiveData 不会自动更新 UI!**
|
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||||
setBackArrow("页面标题")
|
setBackArrow("页面标题")
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
// ⚠️ 关键:必须设置,否则 LiveData 无法自动更新 UI
|
// ⚠️ 关键:必须设置,否则 LiveData 无法自动更新 UI
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**BaseBindingActivity 已自动设置**,但如果手动使用 DataBinding 时务必记住!
|
**BaseBindingActivity 已自动设置**,但如果手动使用 DataBinding 时务必记住!
|
||||||
|
|
||||||
### 📖 ViewModel 中 LiveData 的定义规范
|
#### XML 中 LiveData 的绑定方式
|
||||||
|
|
||||||
```kotlin
|
**1. 单向绑定 `@{}`(只显示,ViewModel → UI)**
|
||||||
class XxxViewModel : BaseViewModel() {
|
|
||||||
// ✅ 推荐:对外暴露不可变的 LiveData
|
|
||||||
private val _dataBean = MutableLiveData<XxxBean>()
|
|
||||||
val dataBean: LiveData<XxxBean> = _dataBean
|
|
||||||
|
|
||||||
// ✅ 简化写法:直接使用 MutableLiveData(项目常用)
|
|
||||||
val searchText = MutableLiveData<String>()
|
|
||||||
val pageType = MutableLiveData(DetailsPageType.Add)
|
|
||||||
|
|
||||||
fun loadData() {
|
|
||||||
// 主线程更新
|
|
||||||
_dataBean.value = XxxBean()
|
|
||||||
|
|
||||||
// 子线程更新(协程中不需要,已在主线程)
|
|
||||||
// _dataBean.postValue(XxxBean())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 📝 XML 中 LiveData 的绑定方式
|
|
||||||
|
|
||||||
#### 1. 单向绑定 `@{}`(只显示,ViewModel → UI)
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<layout>
|
<layout>
|
||||||
@@ -225,7 +335,7 @@ class XxxViewModel : BaseViewModel() {
|
|||||||
type="com.lukouguoji.xxx.XxxViewModel" />
|
type="com.lukouguoji.xxx.XxxViewModel" />
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<!-- LiveData 自动解包:直接访问 value -->
|
<!-- LiveData 自动解包:直接访问 value -->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{viewModel.dataBean.name}" />
|
android:text="@{viewModel.dataBean.name}" />
|
||||||
|
|
||||||
@@ -237,13 +347,13 @@ class XxxViewModel : BaseViewModel() {
|
|||||||
<TextView
|
<TextView
|
||||||
android:text="@{viewModel.dataBean.name ?? `默认值`}" />
|
android:text="@{viewModel.dataBean.name ?? `默认值`}" />
|
||||||
|
|
||||||
<!-- 字符串拼接(使用反引号) -->
|
<!-- 字符串拼接(使用反引号) -->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{`姓名:` + viewModel.dataBean.name}" />
|
android:text="@{`姓名:` + viewModel.dataBean.name}" />
|
||||||
</layout>
|
</layout>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2. 双向绑定 `@={}`(可编辑,UI ↔ ViewModel)
|
**2. 双向绑定 `@={}`(可编辑,UI ↔ ViewModel)**
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- EditText 双向绑定 -->
|
<!-- EditText 双向绑定 -->
|
||||||
@@ -261,15 +371,15 @@ class XxxViewModel : BaseViewModel() {
|
|||||||
value="@={viewModel.dataBean.name}" />
|
value="@={viewModel.dataBean.name}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
**双向绑定要求**:
|
**双向绑定要求**:
|
||||||
- 字段必须是 `MutableLiveData`
|
- 字段必须是 `MutableLiveData`
|
||||||
- 用户输入时自动更新 ViewModel 的值
|
- 用户输入时自动更新 ViewModel 的值
|
||||||
- ViewModel 更新值时自动更新 UI
|
- ViewModel 更新值时自动更新 UI
|
||||||
|
|
||||||
#### 3. 点击事件绑定
|
**3. 点击事件绑定**
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- Lambda 表达式(推荐) -->
|
<!-- Lambda 表达式(推荐) -->
|
||||||
<Button
|
<Button
|
||||||
android:onClick="@{() -> viewModel.submit()}" />
|
android:onClick="@{() -> viewModel.submit()}" />
|
||||||
|
|
||||||
@@ -282,150 +392,64 @@ class XxxViewModel : BaseViewModel() {
|
|||||||
setOnIconClickListener="@{(v) -> viewModel.scanWaybill()}" />
|
setOnIconClickListener="@{(v) -> viewModel.scanWaybill()}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
### ⚠️ DataBinding 常见错误与解决方法
|
#### DataBinding 常见错误与解决方法
|
||||||
|
|
||||||
#### 错误 1:忘记设置 lifecycleOwner
|
**错误 1: 忘记设置 lifecycleOwner**
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误:LiveData 变化但 UI 不更新
|
// ❌ 错误:LiveData 变化但 UI 不更新
|
||||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
// 忘记设置 lifecycleOwner
|
// 忘记设置 lifecycleOwner
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ 正确:必须设置
|
// ✅ 正确:必须设置
|
||||||
override fun initOnCreate(savedInstanceState: Bundle?) {
|
override fun initOnCreate(savedInstanceState: Bundle?) {
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
binding.lifecycleOwner = this // 关键!
|
binding.lifecycleOwner = this // 关键!
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 错误 2:在 XML 中传递 LiveData 而非值
|
**错误 2: 字符串未使用反引号**
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误:某些属性只接受值,不接受 LiveData -->
|
<!-- ❌ 错误:普通引号会被识别为 XML 属性 -->
|
||||||
<View
|
|
||||||
android:visibility="@{viewModel.isVisible}" />
|
|
||||||
<!-- 如果 isVisible 是 MutableLiveData<Boolean>,可能报错 -->
|
|
||||||
|
|
||||||
<!-- ✅ 正确:DataBinding 会自动解包 LiveData -->
|
|
||||||
<View
|
|
||||||
android:visibility="@{viewModel.isVisible ? View.VISIBLE : View.GONE}" />
|
|
||||||
<!-- 三元表达式会自动解包 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 错误 3:import 类型错误
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<!-- ❌ 错误 -->
|
|
||||||
<import type="android.view.View.VISIBLE" />
|
|
||||||
|
|
||||||
<!-- ✅ 正确 -->
|
|
||||||
<import type="android.view.View" />
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 错误 4:字符串未使用反引号
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<!-- ❌ 错误:普通引号会被识别为 XML 属性 -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{"姓名:" + viewModel.name}" />
|
android:text="@{"姓名:" + viewModel.name}" />
|
||||||
|
|
||||||
<!-- ✅ 正确:使用反引号 ` -->
|
<!-- ✅ 正确:使用反引号 ` -->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{`姓名:` + viewModel.name}" />
|
android:text="@{`姓名:` + viewModel.name}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 错误 5:访问 LiveData 的 value 属性
|
**错误 3: 访问 LiveData 的 value 属性**
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误:DataBinding 会自动解包,不需要 .value -->
|
<!-- ❌ 错误:DataBinding 会自动解包,不需要 .value -->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{viewModel.dataBean.value.name}" />
|
android:text="@{viewModel.dataBean.value.name}" />
|
||||||
|
|
||||||
<!-- ✅ 正确:直接访问 -->
|
<!-- ✅ 正确:直接访问 -->
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@{viewModel.dataBean.name}" />
|
android:text="@{viewModel.dataBean.name}" />
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 错误 6:修改对象属性后 UI 不更新
|
**错误 4: 修改对象属性后 UI 不更新**
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误:修改对象内部属性,LiveData 不会触发更新
|
// ❌ 错误:修改对象内部属性,LiveData 不会触发更新
|
||||||
val bean = dataBean.value
|
val bean = dataBean.value
|
||||||
bean?.name = "新名称"
|
bean?.name = "新名称"
|
||||||
// UI 不会更新,因为 LiveData 的引用没变
|
// UI 不会更新,因为 LiveData 的引用没变
|
||||||
|
|
||||||
// ✅ 正确:重新赋值 LiveData
|
// ✅ 正确:重新赋值 LiveData
|
||||||
val bean = dataBean.value?.copy(name = "新名称")
|
val bean = dataBean.value?.copy(name = "新名称")
|
||||||
dataBean.value = bean
|
dataBean.value = bean
|
||||||
|
|
||||||
// ✅ 或者:使用 MutableLiveData + ObservableField
|
|
||||||
// 但项目中更推荐上面的方式
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 错误 7:在 XML 中调用 suspend 函数
|
### 核心 UI 组件详细使用
|
||||||
|
|
||||||
```xml
|
#### PadSearchLayout - 搜索输入框
|
||||||
<!-- ❌ 错误:suspend 函数不能直接在 XML 中调用 -->
|
|
||||||
<Button
|
|
||||||
android:onClick="@{() -> viewModel.loadDataSuspend()}" />
|
|
||||||
|
|
||||||
<!-- ✅ 正确:在 ViewModel 中包装 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
// ViewModel 中
|
|
||||||
fun loadData() { // 普通函数
|
|
||||||
launchLoadingCollect({ NetApply.api.getXxx() }) {
|
|
||||||
onSuccess = { dataBean.value = it.data }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🔍 XML DataBinding 调试技巧
|
|
||||||
|
|
||||||
#### 1. 检查 Binding 类是否生成
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 清理重新构建
|
|
||||||
./gradlew clean
|
|
||||||
./gradlew assembleDebug
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. 查看 DataBinding 错误
|
|
||||||
|
|
||||||
- XML 中的错误可能不会立即显示
|
|
||||||
- 需要 Build 项目才能看到详细错误信息
|
|
||||||
- 错误信息通常在 Build Output 中
|
|
||||||
|
|
||||||
#### 3. 常见错误提示
|
|
||||||
|
|
||||||
```
|
|
||||||
Cannot find the setter for attribute 'android:text' with parameter type...
|
|
||||||
→ 检查属性类型是否匹配
|
|
||||||
|
|
||||||
Unresolved reference: viewModel
|
|
||||||
→ 检查 <variable> 声明和 import
|
|
||||||
|
|
||||||
cannot generate view binders
|
|
||||||
→ 检查 XML 语法错误,特别是 @{} 表达式
|
|
||||||
```
|
|
||||||
|
|
||||||
### 📋 DataBinding 开发检查清单
|
|
||||||
|
|
||||||
- ✅ Activity 中设置 `binding.lifecycleOwner = this`
|
|
||||||
- ✅ ViewModel 中需要双向绑定的字段使用 `MutableLiveData`
|
|
||||||
- ✅ XML 中字符串使用反引号 `` ` ``
|
|
||||||
- ✅ XML 中不访问 LiveData 的 `.value` 属性
|
|
||||||
- ✅ 修改对象属性后重新赋值 LiveData(触发更新)
|
|
||||||
- ✅ 点击事件使用 Lambda 表达式
|
|
||||||
- ✅ 正确 import 枚举和常量类
|
|
||||||
- ✅ XML 错误需要 Build 项目才能看到
|
|
||||||
|
|
||||||
## 核心UI组件
|
|
||||||
|
|
||||||
### PadSearchLayout - 搜索输入框
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- 文本输入+扫码 -->
|
<!-- 文本输入+扫码 -->
|
||||||
@@ -451,13 +475,13 @@ cannot generate view binders
|
|||||||
|
|
||||||
**类型**: `INPUT` / `INTEGER` / `SPINNER` / `DATE`
|
**类型**: `INPUT` / `INTEGER` / `SPINNER` / `DATE`
|
||||||
|
|
||||||
### PadDataLayout - 数据展示/编辑
|
#### PadDataLayout - 数据展示/编辑
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- 文本输入 -->
|
<!-- 文本输入 -->
|
||||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayout
|
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayout
|
||||||
type="@{DataLayoutType.INPUT}"
|
type="@{DataLayoutType.INPUT}"
|
||||||
title='@{"运单号:"}'
|
title='@{"运单号:"}'
|
||||||
titleLength="@{5}"
|
titleLength="@{5}"
|
||||||
value='@={viewModel.bean.waybillNo}'
|
value='@={viewModel.bean.waybillNo}'
|
||||||
enable="@{viewModel.pageType != DetailsPageType.Details}"
|
enable="@{viewModel.pageType != DetailsPageType.Details}"
|
||||||
@@ -467,7 +491,7 @@ cannot generate view binders
|
|||||||
<!-- 下拉选择 -->
|
<!-- 下拉选择 -->
|
||||||
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayout
|
<com.lukouguoji.module_base.ui.weight.data.layout.PadDataLayout
|
||||||
type="@{DataLayoutType.SPINNER}"
|
type="@{DataLayoutType.SPINNER}"
|
||||||
title='@{"状态:"}'
|
title='@{"状态:"}'
|
||||||
list="@{viewModel.statusList}"
|
list="@{viewModel.statusList}"
|
||||||
value='@={viewModel.bean.status}' />
|
value='@={viewModel.bean.status}' />
|
||||||
|
|
||||||
@@ -479,14 +503,15 @@ cannot generate view binders
|
|||||||
```
|
```
|
||||||
|
|
||||||
**类型**: `INPUT` / `SPINNER` / `DATE`
|
**类型**: `INPUT` / `SPINNER` / `DATE`
|
||||||
|
**注意**: 使用 PadDataLayout 时,`titleLength` 通常设置为 5
|
||||||
|
|
||||||
## 开发检查清单
|
### 开发检查清单
|
||||||
|
|
||||||
### ⚠️ 重要提醒
|
#### ⚠️ 重要提醒
|
||||||
|
|
||||||
**新建Activity后必须在AndroidManifest.xml中注册,否则会报ActivityNotFoundException错误!**
|
**新建 Activity 后必须在 AndroidManifest.xml 中注册,否则会报 ActivityNotFoundException 错误!**
|
||||||
|
|
||||||
### 列表页开发(8步)
|
#### 列表页开发 (8步)
|
||||||
|
|
||||||
1. **创建Bean** (`module_base/.../bean/XxxBean.kt`)
|
1. **创建Bean** (`module_base/.../bean/XxxBean.kt`)
|
||||||
2. **添加API接口** (`Api.kt` → `getXxxList()`)
|
2. **添加API接口** (`Api.kt` → `getXxxList()`)
|
||||||
@@ -518,7 +543,7 @@ viewModel.pageModel.bindSmartRefreshLayout(
|
|||||||
binding.recyclerView.addOnItemClickListener(viewModel)
|
binding.recyclerView.addOnItemClickListener(viewModel)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 详情页开发(5步)
|
#### 详情页开发 (5步)
|
||||||
|
|
||||||
1. **添加API接口** (`getXxxDetails()`)
|
1. **添加API接口** (`getXxxDetails()`)
|
||||||
2. **创建ViewModel** (继承`BaseViewModel`)
|
2. **创建ViewModel** (继承`BaseViewModel`)
|
||||||
@@ -539,7 +564,7 @@ companion object {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 编辑页开发(6步)
|
#### 编辑页开发 (6步)
|
||||||
|
|
||||||
1. **添加API接口** (`saveXxx()` + `getXxxDetails()`)
|
1. **添加API接口** (`saveXxx()` + `getXxxDetails()`)
|
||||||
2. **创建ViewModel** (`pageType`使用`MutableLiveData`)
|
2. **创建ViewModel** (`pageType`使用`MutableLiveData`)
|
||||||
@@ -561,14 +586,17 @@ companion object {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun startForEdit(context: Context, id: String) {
|
fun startForEdit(context: Context, id: String) {
|
||||||
/* ... DetailsPageType.Modify ... */
|
val starter = Intent(context, XxxAddActivity::class.java)
|
||||||
|
.putExtra(Constant.Key.PAGE_TYPE, DetailsPageType.Modify.name)
|
||||||
|
.putExtra(Constant.Key.ID, id)
|
||||||
|
context.startActivity(starter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 常见业务场景
|
### 常见业务场景
|
||||||
|
|
||||||
### 扫码
|
#### 扫码
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
fun scanWaybill() {
|
fun scanWaybill() {
|
||||||
@@ -583,7 +611,7 @@ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 图片上传
|
#### 图片上传
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val result = UploadUtil.upload(filePath)
|
val result = UploadUtil.upload(filePath)
|
||||||
@@ -592,7 +620,7 @@ if (result.verifySuccess()) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 列表刷新事件
|
#### 列表刷新事件
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// 发送事件(在ViewModel中)
|
// 发送事件(在ViewModel中)
|
||||||
@@ -607,7 +635,7 @@ FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).observe(this) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 常用扩展函数
|
### 常用扩展函数
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// Toast
|
// Toast
|
||||||
@@ -626,9 +654,9 @@ val dateStr = Date().formatDate() // "2025-11-12"
|
|||||||
permission(Manifest.permission.CAMERA) { openCamera() }
|
permission(Manifest.permission.CAMERA) { openCamera() }
|
||||||
```
|
```
|
||||||
|
|
||||||
## 常见编译错误
|
### 常见编译错误及解决方案
|
||||||
|
|
||||||
### 1. DetailsPageType包名错误
|
#### 1. DetailsPageType 包名错误
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误 -->
|
<!-- ❌ 错误 -->
|
||||||
@@ -638,7 +666,7 @@ permission(Manifest.permission.CAMERA) { openCamera() }
|
|||||||
<import type="com.lukouguoji.module_base.common.DetailsPageType" />
|
<import type="com.lukouguoji.module_base.common.DetailsPageType" />
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. DataLayoutType枚举值错误
|
#### 2. DataLayoutType 枚举值错误
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误: INTEGER不存在 -->
|
<!-- ❌ 错误: INTEGER不存在 -->
|
||||||
@@ -650,7 +678,7 @@ type="@{DataLayoutType.INPUT}"
|
|||||||
|
|
||||||
**可用类型**: `INPUT` / `SPINNER` / `DATE`
|
**可用类型**: `INPUT` / `SPINNER` / `DATE`
|
||||||
|
|
||||||
### 3. DetailsPageType枚举值错误
|
#### 3. DetailsPageType 枚举值错误
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误: Edit不存在
|
// ❌ 错误: Edit不存在
|
||||||
@@ -662,7 +690,7 @@ DetailsPageType.Modify
|
|||||||
|
|
||||||
**可用类型**: `Add` / `Modify` / `Details`
|
**可用类型**: `Add` / `Modify` / `Details`
|
||||||
|
|
||||||
### 4. IOnItemClickListener包名错误
|
#### 4. IOnItemClickListener 包名错误
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误
|
// ❌ 错误
|
||||||
@@ -672,7 +700,7 @@ import com.lukouguoji.module_base.impl.IOnItemClickListener
|
|||||||
import com.lukouguoji.module_base.interfaces.IOnItemClickListener
|
import com.lukouguoji.module_base.interfaces.IOnItemClickListener
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. FlowBus使用错误
|
#### 5. FlowBus 使用错误
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误: observe需要单独导入
|
// ❌ 错误: observe需要单独导入
|
||||||
@@ -691,7 +719,7 @@ viewModelScope.launch {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. 图片上传字段错误
|
#### 6. 图片上传字段错误
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误: UploadBean没有url字段
|
// ❌ 错误: UploadBean没有url字段
|
||||||
@@ -701,7 +729,7 @@ val imageUrl = result.data?.url
|
|||||||
val imageUrl = result.data?.newName
|
val imageUrl = result.data?.newName
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7. pageType必须用LiveData
|
#### 7. pageType 必须用 LiveData
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// ❌ 错误: DataBinding无法绑定
|
// ❌ 错误: DataBinding无法绑定
|
||||||
@@ -711,7 +739,7 @@ var pageType: DetailsPageType = DetailsPageType.Add
|
|||||||
val pageType = MutableLiveData(DetailsPageType.Add)
|
val pageType = MutableLiveData(DetailsPageType.Add)
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8. RecyclerView不支持items属性
|
#### 8. RecyclerView 不支持 items 属性
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误: items属性会导致编译错误 -->
|
<!-- ❌ 错误: items属性会导致编译错误 -->
|
||||||
@@ -729,18 +757,7 @@ viewModel.list.observe(this) { data ->
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 9. Constant.Key.PAGE_TYPE未定义
|
#### 9. 资源引用错误 (最常见的编译失败原因)
|
||||||
|
|
||||||
在`module_base/.../common/Constant.kt`中添加:
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
object Key {
|
|
||||||
const val ID = "id"
|
|
||||||
const val PAGE_TYPE = "pageType" // 添加这个
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 10. 资源引用错误(最常见的编译失败原因)
|
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<!-- ❌ 错误: 引用不存在的资源会导致资源合并失败 -->
|
<!-- ❌ 错误: 引用不存在的资源会导致资源合并失败 -->
|
||||||
@@ -752,12 +769,13 @@ object Key {
|
|||||||
|
|
||||||
**问题原因**:
|
**问题原因**:
|
||||||
- 在布局文件中引用了项目中不存在的 `drawable`、`color`、`string` 等资源
|
- 在布局文件中引用了项目中不存在的 `drawable`、`color`、`string` 等资源
|
||||||
- 导致构建时资源合并失败,无法生成R文件
|
- 导致构建时资源合并失败,无法生成R文件
|
||||||
- 报错信息: `Resource compilation failed` 或 `AAPT: error: resource ... not found`
|
- 报错信息: `Resource compilation failed` 或 `AAPT: error: resource ... not found`
|
||||||
|
|
||||||
**正确做法**:
|
**正确做法**:
|
||||||
|
|
||||||
1. **使用已存在的资源** - 先检查资源是否存在
|
1. **使用已存在的资源** - 先检查资源是否存在
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 查找drawable资源
|
# 查找drawable资源
|
||||||
find module_base/src/main/res/drawable -name "bg_custom*"
|
find module_base/src/main/res/drawable -name "bg_custom*"
|
||||||
@@ -788,27 +806,20 @@ grep "custom_text" module_base/src/main/res/values/strings.xml
|
|||||||
|
|
||||||
3. **使用项目现有资源** - 避免重复创建
|
3. **使用项目现有资源** - 避免重复创建
|
||||||
|
|
||||||
常用资源列表:
|
常用资源列表:
|
||||||
- **背景**: `bg_white_radius_8`, `bg_gray_radius_4`, `bg_primary_radius_4`
|
- **背景**: `bg_white_radius_8`, `bg_gray_radius_4`, `bg_primary_radius_4`
|
||||||
- **颜色**: `white`, `black`, `colorPrimary`, `text_normal`, `text_gray`, `text_red`
|
- **颜色**: `white`, `black`, `colorPrimary`, `text_normal`, `text_gray`, `text_red`
|
||||||
- **文字**: 优先直接写中文字符串,少用 string 资源
|
- **文字**: 优先直接写中文字符串,少用 string 资源
|
||||||
|
|
||||||
**检查清单**:
|
### 错误排查流程
|
||||||
- ✅ 创建/修改布局文件前,确保引用的资源都存在
|
|
||||||
- ✅ 新增drawable时,在正确的module下创建(通常是`module_base`)
|
|
||||||
- ✅ 新增color/string时,添加到对应的values文件中
|
|
||||||
- ✅ 使用IDE的自动补全和资源预览功能,避免拼写错误
|
|
||||||
- ✅ 构建失败时,优先检查资源引用问题
|
|
||||||
|
|
||||||
## 错误排查流程
|
1. **资源引用错误** → 检查drawable/color/string是否存在,主动创建缺失资源
|
||||||
|
|
||||||
1. **资源引用错误** → 检查drawable/color/string是否存在,主动创建缺失资源
|
|
||||||
2. **DataBinding错误** → 检查import包名、枚举值
|
2. **DataBinding错误** → 检查import包名、枚举值
|
||||||
3. **Unresolved reference** → 检查import语句、常量定义
|
3. **Unresolved reference** → 检查import语句、常量定义
|
||||||
4. **suspend function错误** → 在`viewModelScope.launch`中调用
|
4. **suspend function错误** → 在`viewModelScope.launch`中调用
|
||||||
5. **仍有问题** → `./gradlew clean` 后重新构建
|
5. **仍有问题** → `./gradlew clean` 后重新构建
|
||||||
|
|
||||||
## 快速修复命令
|
### 快速修复命令
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 查找DetailsPageType位置
|
# 查找DetailsPageType位置
|
||||||
@@ -821,37 +832,134 @@ find module_base/src -name "IOnItemClickListener.kt"
|
|||||||
grep -A 5 "enum class DataLayoutType" module_base/src --include="*.kt"
|
grep -A 5 "enum class DataLayoutType" module_base/src --include="*.kt"
|
||||||
```
|
```
|
||||||
|
|
||||||
## 开发原则
|
### 布局最佳实践参考
|
||||||
|
|
||||||
- ✅ **资源引用必须存在** - 创建/修改布局前,确保drawable/color/string资源真实存在或主动创建
|
参考以下文件进行布局设计:
|
||||||
- ✅ **必须设置 lifecycleOwner** - Activity 中 `binding.lifecycleOwner = this`(BaseBindingActivity 已自动设置)
|
- `module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml`
|
||||||
|
- `module_gjc/src/main/res/layout/item_gjc_check_in_record.xml`
|
||||||
|
- `module_gjc/src/main/res/layout/activity_gjc_box_weighing_details.xml`
|
||||||
|
- `module_gjc/src/main/res/layout/activity_gjc_inspection.xml`
|
||||||
|
|
||||||
|
### 开发原则
|
||||||
|
|
||||||
|
- ✅ **资源引用必须存在** - 创建/修改布局前,确保drawable/color/string资源真实存在或主动创建
|
||||||
|
- ✅ **必须设置 lifecycleOwner** - Activity 中 `binding.lifecycleOwner = this`(BaseBindingActivity 已自动设置)
|
||||||
|
- ✅ **新建Activity后必须在AndroidManifest.xml中注册**
|
||||||
- ✅ 优先使用项目现有基类和封装
|
- ✅ 优先使用项目现有基类和封装
|
||||||
- ✅ 充分利用PadDataLayout和PadSearchLayout组件
|
- ✅ 充分利用PadDataLayout和PadSearchLayout组件
|
||||||
- ✅ 遵循统一命名规范
|
- ✅ 遵循统一命名规范
|
||||||
- ✅ pageType用LiveData不用普通变量
|
- ✅ pageType用LiveData不用普通变量
|
||||||
- ✅ XML中字符串拼接使用反引号,不访问LiveData的.value属性
|
- ✅ XML中字符串拼接使用反引号,不访问LiveData的.value属性
|
||||||
- ✅ 修改对象属性后重新赋值LiveData才能触发UI更新
|
- ✅ 修改对象属性后重新赋值LiveData才能触发UI更新
|
||||||
- ✅ FlowBus.emit()必须在协程中调用
|
- ✅ FlowBus.emit()必须在协程中调用
|
||||||
- ✅ 图片上传使用newName字段
|
- ✅ 图片上传使用newName字段
|
||||||
- ✅ RecyclerView手动更新adapter不用items属性
|
- ✅ RecyclerView手动更新adapter不用items属性
|
||||||
- ✅ 新建Activity后必须在AndroidManifest.xml中注册
|
- ✅ 在每个页面布局时,如有截图,务必尽可能还原图片上的页面设计,而不是推测假想。如有困难(图片看不清、不明白的地方)一律要询问,禁止自己想象。
|
||||||
|
|
||||||
## 技术栈
|
|
||||||
|
|
||||||
- Kotlin + 协程 1.6.0
|
|
||||||
- Retrofit 2.6.1 + OkHttp 3.12.12
|
|
||||||
- DataBinding + LiveData
|
|
||||||
- ARouter 1.5.2
|
|
||||||
- SmartRefreshLayout 2.0.3
|
|
||||||
- Glide 4.15.1
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**签名配置**: `key.jks` / 密码: `123321` / 别名: `key`
|
## Universal Development Guidelines
|
||||||
- 当使用PadDataLayoutNew 控件的时候,titleLength 通常设置为5
|
|
||||||
- 在每个页面布局时,我会给你截图,请务必尽可能还原图片上的页面设计,而不是推测、假想。如果有困难(例如图片看不清,不明白的地方)一律要询问我,禁止自己想象。
|
### Code Quality Standards
|
||||||
- layout xml 最佳布局实践参考:
|
- Write clean, readable, and maintainable code
|
||||||
- module_gjc/src/main/res/layout/activity_gjc_weighing_record_details.xml
|
- Follow consistent naming conventions across the project
|
||||||
- module_gjc/src/main/res/layout/item_gjc_check_in_record.xml
|
- Use meaningful variable and function names
|
||||||
- module_gjc/src/main/res/layout/activity_gjc_box_weighing_details.xml
|
- Keep functions focused and single-purpose
|
||||||
- module_gjc/src/main/res/layout/activity_gjc_inspection.xml
|
- Add comments for complex logic and business rules
|
||||||
|
|
||||||
|
### Git Workflow
|
||||||
|
- Use descriptive commit messages following conventional commits format
|
||||||
|
- Create feature branches for new development
|
||||||
|
- Keep commits atomic and focused on single changes
|
||||||
|
- Use pull requests for code review before merging
|
||||||
|
- Maintain a clean commit history
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- Keep README.md files up to date
|
||||||
|
- Document public APIs and interfaces
|
||||||
|
- Include usage examples for complex features
|
||||||
|
- Maintain inline code documentation
|
||||||
|
- Update documentation when making changes
|
||||||
|
|
||||||
|
### Testing Approach
|
||||||
|
- Write tests for new features and bug fixes
|
||||||
|
- Maintain good test coverage
|
||||||
|
- Use descriptive test names that explain the expected behavior
|
||||||
|
- Organize tests logically by feature or module
|
||||||
|
- Run tests before committing changes
|
||||||
|
|
||||||
|
### Security Best Practices
|
||||||
|
- Never commit sensitive information (API keys, passwords, tokens)
|
||||||
|
- Use environment variables for configuration
|
||||||
|
- Validate input data and sanitize outputs
|
||||||
|
- Follow principle of least privilege
|
||||||
|
- Keep dependencies updated
|
||||||
|
|
||||||
|
## Project Structure Guidelines
|
||||||
|
|
||||||
|
### File Organization
|
||||||
|
- Group related files in logical directories
|
||||||
|
- Use consistent file and folder naming conventions
|
||||||
|
- Separate source code from configuration files
|
||||||
|
- Keep build artifacts out of version control
|
||||||
|
- Organize assets and resources appropriately
|
||||||
|
|
||||||
|
### Configuration Management
|
||||||
|
- Use configuration files for environment-specific settings
|
||||||
|
- Centralize configuration in dedicated files
|
||||||
|
- Use environment variables for sensitive or environment-specific data
|
||||||
|
- Document configuration options and their purposes
|
||||||
|
- Provide example configuration files
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Before Starting Work
|
||||||
|
1. Pull latest changes from main branch
|
||||||
|
2. Create a new feature branch
|
||||||
|
3. Review existing code and architecture
|
||||||
|
4. Plan the implementation approach
|
||||||
|
|
||||||
|
### During Development
|
||||||
|
1. Make incremental commits with clear messages
|
||||||
|
2. Run tests frequently to catch issues early
|
||||||
|
3. Follow established coding standards
|
||||||
|
4. Update documentation as needed
|
||||||
|
|
||||||
|
### Before Submitting
|
||||||
|
1. Run full test suite
|
||||||
|
2. Check code quality and formatting
|
||||||
|
3. Update documentation if necessary
|
||||||
|
4. Create clear pull request description
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
- Use appropriate error handling mechanisms for the language
|
||||||
|
- Provide meaningful error messages
|
||||||
|
- Log errors appropriately for debugging
|
||||||
|
- Handle edge cases gracefully
|
||||||
|
- Don't expose sensitive information in error messages
|
||||||
|
|
||||||
|
### Performance Considerations
|
||||||
|
- Profile code for performance bottlenecks
|
||||||
|
- Optimize database queries and API calls
|
||||||
|
- Use caching where appropriate
|
||||||
|
- Consider memory usage and resource management
|
||||||
|
- Monitor and measure performance metrics
|
||||||
|
|
||||||
|
### Code Reusability
|
||||||
|
- Extract common functionality into reusable modules
|
||||||
|
- Use dependency injection for better testability
|
||||||
|
- Create utility functions for repeated operations
|
||||||
|
- Design interfaces for extensibility
|
||||||
|
- Follow DRY (Don't Repeat Yourself) principle
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
Before marking any task as complete:
|
||||||
|
- [ ] Code follows established conventions
|
||||||
|
- [ ] Tests are written and passing
|
||||||
|
- [ ] Documentation is updated
|
||||||
|
- [ ] Security considerations are addressed
|
||||||
|
- [ ] Performance impact is considered
|
||||||
|
- [ ] Code is reviewed for maintainability
|
||||||
273
CONTRIBUTING.md
Normal file
273
CONTRIBUTING.md
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
# 贡献指南 (Contributing Guide)
|
||||||
|
|
||||||
|
感谢你对 AirLogistics 项目的关注!本文档将指导你如何参与项目开发。
|
||||||
|
|
||||||
|
## 开发环境搭建
|
||||||
|
|
||||||
|
### 前置要求
|
||||||
|
|
||||||
|
- **IDE**: Android Studio Arctic Fox (2020.3.1) 或更高版本
|
||||||
|
- **JDK**: JDK 1.8
|
||||||
|
- **Gradle**: 7.3.3 (使用项目内置的 Gradle Wrapper)
|
||||||
|
- **Kotlin**: 1.6.21 (已在项目中配置)
|
||||||
|
- **Android SDK**: API 24-31
|
||||||
|
|
||||||
|
### 克隆项目
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone ssh://git@git.njcqit.com:2222/eric/aerologic-app.git
|
||||||
|
cd aerologic-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置 Android SDK
|
||||||
|
|
||||||
|
1. 创建 `local.properties` 文件 (如果不存在):
|
||||||
|
```properties
|
||||||
|
sdk.dir=/path/to/your/android/sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 在 Android Studio 中:
|
||||||
|
- 打开项目
|
||||||
|
- 等待 Gradle 同步完成
|
||||||
|
- 如提示 SDK 路径问题,在 Settings → Android SDK 中配置
|
||||||
|
|
||||||
|
### Gradle 依赖配置
|
||||||
|
|
||||||
|
项目已配置阿里云 Maven 镜像和私有仓库,正常情况下依赖会自动下载。
|
||||||
|
|
||||||
|
如遇依赖下载问题:
|
||||||
|
1. 下载 gradle-7.3.3-bin.zip
|
||||||
|
- 百度网盘: https://pan.baidu.com/s/18wsuGRlNxjMYbxLhBH9yeg
|
||||||
|
- 提取码: 1029
|
||||||
|
|
||||||
|
2. 配置 Gradle:
|
||||||
|
- Settings → Build, Execution, Deployment → Build Tools → Gradle
|
||||||
|
- 解压并替换到 "Gradle user home" 目录
|
||||||
|
|
||||||
|
## 项目构建
|
||||||
|
|
||||||
|
### 首次构建
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 清理并构建 Debug 版本
|
||||||
|
./gradlew clean assembleDebug
|
||||||
|
|
||||||
|
# 或使用快捷命令
|
||||||
|
/clean-build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 常用构建命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建 Debug APK
|
||||||
|
./gradlew assembleDebug
|
||||||
|
# 或使用: /build-debug
|
||||||
|
|
||||||
|
# 构建 Release APK (已签名)
|
||||||
|
./gradlew assembleRelease
|
||||||
|
# 或使用: /build-release
|
||||||
|
|
||||||
|
# 安装到设备
|
||||||
|
./gradlew installDebug
|
||||||
|
# 或使用: /install
|
||||||
|
|
||||||
|
# 运行代码检查
|
||||||
|
./gradlew lint
|
||||||
|
# 或使用: /lint
|
||||||
|
|
||||||
|
# 查看已连接设备
|
||||||
|
adb devices -l
|
||||||
|
# 或使用: /devices
|
||||||
|
|
||||||
|
# 查看应用日志
|
||||||
|
adb logcat | grep "com.lukouguoji.aerologic"
|
||||||
|
# 或使用: /logs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 组件化开发模式
|
||||||
|
|
||||||
|
项目支持模块独立运行,方便单模块调试:
|
||||||
|
|
||||||
|
1. 编辑 `gradle.properties`
|
||||||
|
2. 设置 `isBuildModule=true` (独立运行) 或 `false` (集成模式)
|
||||||
|
3. Sync 项目
|
||||||
|
4. 运行对应模块
|
||||||
|
|
||||||
|
**注意**: 切换模式后需要重新 Sync 项目。
|
||||||
|
|
||||||
|
## 分支策略
|
||||||
|
|
||||||
|
### 分支类型
|
||||||
|
|
||||||
|
- **main**: 主分支,用于发布稳定版本
|
||||||
|
- **feature/xxx**: 功能开发分支 (例: `feature/cargo-tracking`)
|
||||||
|
- **hotfix/xxx**: 紧急修复分支 (例: `hotfix/login-crash`)
|
||||||
|
- **refactor/xxx**: 重构分支 (例: `refactor/network-layer`)
|
||||||
|
|
||||||
|
### 分支命名规范
|
||||||
|
|
||||||
|
- 使用小写字母和连字符
|
||||||
|
- 功能分支: `feature/功能名称-简短描述`
|
||||||
|
- 修复分支: `hotfix/问题简述`
|
||||||
|
- 重构分支: `refactor/重构范围`
|
||||||
|
|
||||||
|
### 工作流程
|
||||||
|
|
||||||
|
1. 从 main 分支创建新分支:
|
||||||
|
```bash
|
||||||
|
git checkout main
|
||||||
|
git pull
|
||||||
|
git checkout -b feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 在新分支上开发并提交
|
||||||
|
|
||||||
|
3. 推送到远程仓库:
|
||||||
|
```bash
|
||||||
|
git push -u origin feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
4. 创建 Pull Request,等待代码审查
|
||||||
|
|
||||||
|
## 提交规范
|
||||||
|
|
||||||
|
### Conventional Commits 格式
|
||||||
|
|
||||||
|
提交信息应遵循以下格式:
|
||||||
|
|
||||||
|
```
|
||||||
|
<类型>: <简短描述>
|
||||||
|
|
||||||
|
[可选的详细说明]
|
||||||
|
|
||||||
|
[可选的 footer]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 提交类型
|
||||||
|
|
||||||
|
- **feat**: 新功能 (例: `feat: 添加国内出港货物复磅功能`)
|
||||||
|
- **fix**: Bug修复 (例: `fix: 修复登录页面崩溃问题`)
|
||||||
|
- **refactor**: 代码重构 (例: `refactor: 优化网络请求层架构`)
|
||||||
|
- **docs**: 文档更新 (例: `docs: 更新 README 安装说明`)
|
||||||
|
- **style**: 代码格式调整 (例: `style: 格式化 LoginActivity 代码`)
|
||||||
|
- **test**: 测试相关 (例: `test: 添加货物追踪单元测试`)
|
||||||
|
- **chore**: 构建/工具相关 (例: `chore: 升级 Kotlin 到 1.6.21`)
|
||||||
|
|
||||||
|
### 提交示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 好的提交信息
|
||||||
|
git commit -m "feat: 添加国际进港舱单管理功能"
|
||||||
|
git commit -m "fix: 修复蓝牙打印机连接失败问题"
|
||||||
|
git commit -m "refactor: 重构 BaseViewModel 生命周期管理"
|
||||||
|
|
||||||
|
# 不好的提交信息
|
||||||
|
git commit -m "update"
|
||||||
|
git commit -m "修改了一些文件"
|
||||||
|
git commit -m "功能完成"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码审查流程
|
||||||
|
|
||||||
|
### 创建 Pull Request
|
||||||
|
|
||||||
|
1. 确保代码已推送到远程仓库
|
||||||
|
2. 在 Git 托管平台创建 Pull Request
|
||||||
|
3. 填写 PR 描述:
|
||||||
|
- 功能说明
|
||||||
|
- 变更内容
|
||||||
|
- 测试情况
|
||||||
|
- 相关 Issue (如有)
|
||||||
|
|
||||||
|
### 代码审查要点
|
||||||
|
|
||||||
|
审查者应关注:
|
||||||
|
- [ ] 代码是否符合项目架构和规范
|
||||||
|
- [ ] 是否使用了正确的基类 (BaseActivity, BaseViewModel等)
|
||||||
|
- [ ] DataBinding 和协程使用是否正确
|
||||||
|
- [ ] 命名是否清晰、符合约定
|
||||||
|
- [ ] 是否有明显的性能问题
|
||||||
|
- [ ] 是否有代码重复或可复用的逻辑
|
||||||
|
|
||||||
|
### 合并前检查清单
|
||||||
|
|
||||||
|
提交者在创建 PR 前应确保:
|
||||||
|
- [ ] 代码编译通过,无编译错误
|
||||||
|
- [ ] 遵循项目命名和文件组织规范
|
||||||
|
- [ ] 使用了项目提供的基类和工具类
|
||||||
|
- [ ] DataBinding 正确使用
|
||||||
|
- [ ] 协程和 Flow 使用规范
|
||||||
|
- [ ] 无明显的内存泄漏风险
|
||||||
|
- [ ] 已在真机或模拟器上测试
|
||||||
|
- [ ] 提交信息符合规范
|
||||||
|
|
||||||
|
## 开发注意事项
|
||||||
|
|
||||||
|
### 架构要求
|
||||||
|
|
||||||
|
1. **优先使用现有基类**
|
||||||
|
- Activity 继承 `BaseActivity` 或 `BaseBindingActivity`
|
||||||
|
- ViewModel 继承 `BaseViewModel` 或 `BasePageViewModel`
|
||||||
|
- 列表适配器使用 `CommonAdapter` + `BaseViewHolder`
|
||||||
|
|
||||||
|
2. **使用统一 UI 组件**
|
||||||
|
- 搜索输入: 使用 `PadSearchLayout`
|
||||||
|
- 数据展示: 使用 `PadDataLayout`
|
||||||
|
- 遵循全局样式规范 (colors, dimens, styles)
|
||||||
|
|
||||||
|
3. **网络请求规范**
|
||||||
|
- 使用 `launchCollect` 或 `launchLoadingCollect` 扩展函数
|
||||||
|
- API 定义在对应模块的 `api/` 目录下
|
||||||
|
- 数据模型继承 `BaseResultBean` 或 `BaseListBean`
|
||||||
|
|
||||||
|
### 代码风格
|
||||||
|
|
||||||
|
- 遵循 Kotlin 官方编码规范
|
||||||
|
- 使用有意义的变量名和函数名
|
||||||
|
- 避免过长的函数,单个函数不超过 50 行
|
||||||
|
- 复杂逻辑添加注释说明
|
||||||
|
|
||||||
|
### 安全要求
|
||||||
|
|
||||||
|
- **禁止提交敏感信息**:
|
||||||
|
- API密钥
|
||||||
|
- 密码
|
||||||
|
- Token
|
||||||
|
- 个人信息
|
||||||
|
- 签名文件 (key.jks 已在 .gitignore 中)
|
||||||
|
|
||||||
|
- **配置信息管理**:
|
||||||
|
- 服务器地址配置在 `module_base/res/values/strings.xml`
|
||||||
|
- 本地开发配置使用 `local.properties`
|
||||||
|
- 运行时配置使用 SharedPreferences
|
||||||
|
|
||||||
|
## 模块开发规范
|
||||||
|
|
||||||
|
### 新增业务页面
|
||||||
|
|
||||||
|
1. 在对应模块的 `ui/page/` 目录下创建 Activity
|
||||||
|
2. 在 `service/viewModel/` 目录下创建 ViewModel
|
||||||
|
3. 在 `bean/` 目录下定义数据模型
|
||||||
|
4. 布局文件使用 DataBinding
|
||||||
|
|
||||||
|
### 模块间通信
|
||||||
|
|
||||||
|
- 使用 ARouter 进行页面跳转
|
||||||
|
- 路由路径定义在 `module_base/router/` 目录
|
||||||
|
- 事件通信使用 FlowBus 或 EventBus
|
||||||
|
|
||||||
|
## 获取帮助
|
||||||
|
|
||||||
|
如有问题或建议,可以通过以下方式:
|
||||||
|
|
||||||
|
1. 查看项目文档:
|
||||||
|
- [CLAUDE.md](./CLAUDE.md) - 详细开发指南
|
||||||
|
- [README.md](./README.md) - 项目概览
|
||||||
|
|
||||||
|
2. 联系项目维护者
|
||||||
|
|
||||||
|
3. 提交 Issue (如果支持)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
再次感谢你的贡献!🎉
|
||||||
Reference in New Issue
Block a user