60 lines
2.5 KiB
Markdown
60 lines
2.5 KiB
Markdown
|
|
# Code Review — Android Compose Migration — 2026-04-02
|
|||
|
|
|
|||
|
|
## Summary
|
|||
|
|
|
|||
|
|
XML layouts + Fragments 全部迁移到 Jetpack Compose。12 个新文件,删除 2596 行 XML/Fragment 代码。Linear 深色主题落地,组件库复用良好。
|
|||
|
|
|
|||
|
|
## 整体评价
|
|||
|
|
|
|||
|
|
**做得好:**
|
|||
|
|
- 色板、字体、组件库完全按 REDESIGN.md 规范
|
|||
|
|
- `LaunchedEffect` + `mutableStateOf` 状态管理干净
|
|||
|
|
- `SectionCard`, `KeyValueRow`, `ToggleRow`, `NavigationRow` 复用率高
|
|||
|
|
- Bottom sheet 替代 expand,交互更现代
|
|||
|
|
- LogsScreen 增量读取 (`RandomAccessFile` + delta) 设计巧妙
|
|||
|
|
- ConfigScreen 分组列表紧凑,inline dropdown 比 Spinner 更好
|
|||
|
|
|
|||
|
|
## Bugs
|
|||
|
|
|
|||
|
|
### B1. LogsScreen 重复定义 InlineDivider
|
|||
|
|
|
|||
|
|
`ui/screens/LogsScreen.kt:126-128` 定义了私有 `InlineDivider`,但 `ui/components/Components.kt:162-168` 已有公共版本。
|
|||
|
|
|
|||
|
|
**Fix:** 删除 LogsScreen 中的私有版本,import 公共组件。
|
|||
|
|
|
|||
|
|
### B2. ConfigScreen 双重 save
|
|||
|
|
|
|||
|
|
每个 `onValueChange` 调用 `save()`,`DisposableEffect(Unit)` 的 `onDispose` 也调 `save()`。每次输入字符都写全量 SharedPreferences,不必要。
|
|||
|
|
|
|||
|
|
**Fix:** 去掉 `onValueChange` 里的 `save()` 调用,只保留 `DisposableEffect` 的 `onDispose { save() }`。对于 toggle 类(立即生效),单独 `prefs.edit().putBoolean(...).apply()`。
|
|||
|
|
|
|||
|
|
### B3. OverviewScreen recentConnections 缺 key
|
|||
|
|
|
|||
|
|
`OverviewScreen.kt:169` 的 `items(recentConnections.take(5))` 没有 `key` 参数,列表更新时 Compose 无法高效 diff,导致不必要的重组。
|
|||
|
|
|
|||
|
|
**Fix:** 添加 `key = { it.host }` 或用 index。
|
|||
|
|
|
|||
|
|
## Improvements
|
|||
|
|
|
|||
|
|
### I1. 字符串硬编码
|
|||
|
|
|
|||
|
|
所有 UI 文字直接写在 Compose 代码里("Paste URI", "Subscription URL", "Not connected" 等)。`strings.xml` 已被清空。
|
|||
|
|
|
|||
|
|
**Impact:** 不影响功能,但阻碍了国际化。后续统一迁移到 `stringResource()`。
|
|||
|
|
|
|||
|
|
### I2. fragment-ktx 依赖可移除
|
|||
|
|
|
|||
|
|
Compose 迁移后不再需要 `androidx.fragment:fragment-ktx`。build.gradle.kts 中已移除,确认无残留引用即可。
|
|||
|
|
|
|||
|
|
### I3. NodesScreen 函数过长
|
|||
|
|
|
|||
|
|
`NodesScreen.kt` 单个 Composable 约 400 行,包含 bottom sheet、import 逻辑、tab 切换。
|
|||
|
|
|
|||
|
|
**Suggestion:** 拆分为 `NodeActionSheet`、`ImportSheet`、`ProxyNodeList`、`TailscalePeerList` 独立 Composable。
|
|||
|
|
|
|||
|
|
### I4. fetchTrafficStats / fetchConnections 重复
|
|||
|
|
|
|||
|
|
`OverviewScreen.kt:289` 和 `ConnectionsScreen.kt:141` 各自实现了 Clash API 的 `/connections` 解析,逻辑几乎相同。
|
|||
|
|
|
|||
|
|
**Suggestion:** 抽取到 `data/ClashApi.kt` 统一调用。
|