perf(reader): M29 书架扫描缓存 + 行数多时关圆角容器(回书架 3.4s→0.03s,滚动 52ms→19ms)
真机(0.8.48 / reader 0.1.1 基线,同机同字库 ztest 实测): - 从阅读页返回书架:3435ms(3259–3531)→ 33ms(24–54)。根因是 shelf_on_enter 无条件 scan_books():exFAT 全量扫描 434 目录 = 3.1s。改为进程内缓存(首次进入才扫,顶栏 「刷新」强制重扫);truncated/depth_skipped 提示语义不变(首次扫描时算好并保留)。 行为变化:新进 Books/ 的书、刚读完那本书的「最近阅读置顶」需点一次「刷新」才更新。 - 书架滑动每步(62px,含 widget_draw + flush):51.9–56.2ms → 19.3–19.9ms。 行数 > 200 时 meow_listview_set_container(0)(扁平行),≤200 行仍用 MD3 圆角卡; 圆角卡走 meow_gfx_fill_round 逐像素 rr_inside(464×54 一张 3.8–6.4ms ×11 行)。 - 首次进书架仍需扫一次(3497ms,含 3157ms 扫描);595 本全可见、format/folder 分组不变。 另加 test/shelf_bench_ondev.c(真机耗时基准,不进 mpk)与 build_reader.sh 的编译步骤; app.json 0.1.1/2 → 0.1.2/3。未做(按塔砍范围):字体路径记忆化、首屏只渲染当前页、 自绘行、mtime 失效检测。
This commit is contained in:
1 parent
288c133efc
commit
bece9848e7
5 files changed
+151
-6
No files matched your search
@@ -2,8 +2,9 @@
|
||||
* 其它显示「R2 支持」占位);MD3 布局(meow_topappbar + list/grid)+ 最近阅读置顶 + 段头分组。
|
||||
*
|
||||
* 布局(README §3.2,用户 2026-09-04 拍板):
|
||||
* - 默认 list(meow_listview_set_container(on) MD3 圆角卡),可切 grid(meow_lazygrid 4 列封面卡);
|
||||
* 布局存 reader.conf `ui.shelf_layout`(rdconf_get()->shelf);
|
||||
* - 默认 list(meow_listview_set_container(on) MD3 圆角卡;**行数 > SHELF_ROUND_MAX_ROWS
|
||||
* 时自动降级为扁平行**——圆角卡逐像素填充太慢,见 shelf_build_content 注释),
|
||||
* 可切 grid(meow_lazygrid 4 列封面卡);布局存 reader.conf `ui.shelf_layout`;
|
||||
* - 顶栏 meow_topappbar:标题「书架」+ 动作(布局切换 / 分组切换 / 刷新 / App 设置入口);
|
||||
* - 无书也渲染完整骨架(顶栏 + 内容区 + 居中空态卡 + 指引 + 支持格式);
|
||||
* - 封面:MVP 无封面提取(engine F1);无则圆角占位(surfaceContainerHigh + 格式徽标)。
|
||||
@@ -12,6 +13,12 @@
|
||||
* format = 按格式分段(TXT/FB2/EPUB/MOBI/CBZ);
|
||||
* folder = 按 Books/ 下的「第一级目录」分段(根下=未分类),更深子路径(分类/作品)进副题。
|
||||
* 扫描/行序列在 app/shelf_model.c(纯 C,宿主可测);本文件只做控件装配与绘制。
|
||||
*
|
||||
* M29 性能(用户反馈「几百本书首页卡得飞起」):
|
||||
* - **扫描结果进程内缓存**:只在本进程首次进入书架时扫 Books/;从阅读页返回不再重扫
|
||||
* (真机 exFAT 全量扫描 3.1s,是「回书架冻结」的唯一大头)。顶栏「刷新」强制重扫。
|
||||
* 行为变化:新放进 Books/ 的书、以及刚读完那本书的「最近阅读置顶」需点一次「刷新」才更新。
|
||||
* - **行数多时关圆角容器**(见 SHELF_ROUND_MAX_ROWS):圆角卡逐像素填充,595 本时滑一步 46ms。
|
||||
*/
|
||||
#include "../reader_internal.h"
|
||||
#include "progress.h"
|
||||
@@ -25,9 +32,12 @@
|
||||
#define SHELF_APPBAR_H 56
|
||||
#define SHELF_LIST_X 0
|
||||
#define SHELF_LIST_W 480
|
||||
/* 圆角卡容器阈值:行数 ≤ 该值用 MD3 圆角卡(观感优先),超过则扁平行(滚动流畅优先)。 */
|
||||
#define SHELF_ROUND_MAX_ROWS 200
|
||||
|
||||
static shelf_book g_books[SHELF_MAX_BOOKS];
|
||||
static int g_nbooks;
|
||||
static int g_scanned; /* 1=本进程已扫过 Books/(进书架缓存;「刷新」动作强制重扫) */
|
||||
static int g_active;
|
||||
static meow_widget *g_list; /* listview(布局=list) */
|
||||
static meow_lazygrid *g_grid; /* lazygrid(布局=grid) */
|
||||
@@ -61,6 +71,7 @@ static void notice_set(const char *line1, const char *line2)
|
||||
g_notice_until = meow_ui_time_ms() + 6000; /* 6s 后由 shelf_on_tick 清掉,不常驻压列表 */
|
||||
}
|
||||
|
||||
/* 扫描 Books/ 并写入 g_books/g_nbooks(同时更新提示条)。首次进入书架与顶栏「刷新」才调。 */
|
||||
static void scan_books(void)
|
||||
{
|
||||
const char *dir = READER_SD_ROOT "/Books";
|
||||
@@ -69,6 +80,7 @@ static void scan_books(void)
|
||||
g_notice_ms = 0;
|
||||
shelf_scan_report rep;
|
||||
g_nbooks = shelf_scan_books(dir, g_books, SHELF_MAX_BOOKS, shelf_ts_of, &rep);
|
||||
g_scanned = 1;
|
||||
if (rep.root_missing) {
|
||||
char line[160];
|
||||
snprintf(line, sizeof line, "未找到 %s 目录,请放入书籍(TXT)", dir);
|
||||
@@ -223,7 +235,11 @@ static void shelf_build_content(void)
|
||||
g_nrows, NULL, NULL, MEOW_LIST_SEL_SINGLE);
|
||||
if (g_list) {
|
||||
meow_listview_set_vsource(g_list, shelf_list_count, shelf_list_bind, NULL);
|
||||
meow_listview_set_container(g_list, 1);
|
||||
/* MD3 圆角容器(surfaceContainer 卡)走 meow_gfx_fill_round 逐像素 rr_inside:
|
||||
* 真机一张 464×54 卡 3.8–6.4ms、可见 11 行≈42ms/帧(滑一步 46ms)。行数多时
|
||||
* 自动降级为扁平行(survey 实测同滚动 14ms),行数少(≤SHELF_ROUND_MAX_ROWS)
|
||||
* 仍保留圆角卡观感。 */
|
||||
meow_listview_set_container(g_list, g_nrows > SHELF_ROUND_MAX_ROWS ? 0 : 1);
|
||||
meow_listview_set_item_tier(g_list, 2);
|
||||
meow_listview_set_on_tap(g_list, shelf_list_tapcb, NULL);
|
||||
}
|
||||
@@ -256,7 +272,11 @@ static void shelf_on_enter(meow_view *v, void *ctx)
|
||||
const rdconf *c = rdconf_get();
|
||||
g_layout = (c && c->shelf[0] && strcmp(c->shelf, "grid") == 0) ? 1 : 0;
|
||||
g_group_folder = (c && strcmp(c->shelf_group, "folder") == 0) ? 1 : 0;
|
||||
scan_books(); /* 回到书架即重扫(新增/最近读置顶刷新) */
|
||||
/* 书架缓存:本进程只在首次进入时扫一次 Books/(从阅读页返回不再重扫)。
|
||||
* 扫描在真机是 3.1s(exFAT 434 目录 opendir/readdir),是「回书架冻结」的唯一大头。
|
||||
* 代价:新放入的书 / 刚读完的书不会自动置顶,需点顶栏「刷新」(强制重扫)。
|
||||
* 提示条(超上限截断 / 超深目录)语义不变:首次扫描时算好并保留在 g_notice*。 */
|
||||
if (!g_scanned) scan_books();
|
||||
build_rows();
|
||||
const meow_theme *th = meow_theme_get();
|
||||
g_bg = th->bg; g_fg = th->fg; g_dim = th->dim;
|
||||
@@ -383,7 +403,8 @@ int shelf_on_tap(int x, int y)
|
||||
} else if (bi == 1) { /* 分组切换:format ↔ folder */
|
||||
shelf_set_group(g_group_folder ? 0 : 1);
|
||||
return 1;
|
||||
} else if (bi == 2) { /* 刷新:重扫 */
|
||||
} else if (bi == 2) { /* 刷新:强制重扫(缓存失效 + 重扫;新书/刚读完的书在此出现) */
|
||||
g_scanned = 0;
|
||||
scan_books(); build_rows();
|
||||
shelf_build_content();
|
||||
shelf_redraw();
|
||||
|
||||
Reference in new issue
Block a user