From 14161727d5a4fbc3f8dd2db0fee0581ccea95576 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 28 Jan 2026 12:21:28 +0800 Subject: [PATCH] docs: Sync documentation with codebase and fix bugs - Fix README.md duplicate ')' syntax error - Fix IsolateEventStorage response format (add missing id/ok fields) - Update todo list with Isolate storage and lifecycle features - Add maxEventAge config explanation to design doc - Update lifecycle description in overview doc --- 0.总体目标与边界.md | 4 ++-- 2.Flutter 埋点 SDK 设计方案(独立 Dart 实现).md | 7 +++++++ 3.Flutter todo list.md | 2 +- README.md | 8 ++++++-- analysis_options.yaml | 2 -- lib/src/storage/isolate_event_storage.dart | 4 ++++ 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/0.总体目标与边界.md b/0.总体目标与边界.md index dc73155..d61de19 100644 --- a/0.总体目标与边界.md +++ b/0.总体目标与边界.md @@ -133,8 +133,8 @@ SDK 内部统一分层: - `Timer.periodic` 实现定时 flush - 控制并发:用一个「上传中」标志避免并发多次 flush - 生命周期: - - SDK 暴露 `flush()`; - - 应用可在自身生命周期(如 `WidgetsBindingObserver` 或 Router)中调用。 + - SDK 已实现 `Analytics.bindLifecycleObserver()`,自动在后台/销毁时 flush; + - 应用也可手动调用 `flush()`。 ## 3.2 Android SDK diff --git a/2.Flutter 埋点 SDK 设计方案(独立 Dart 实现).md b/2.Flutter 埋点 SDK 设计方案(独立 Dart 实现).md index a7eb7a9..b000434 100644 --- a/2.Flutter 埋点 SDK 设计方案(独立 Dart 实现).md +++ b/2.Flutter 埋点 SDK 设计方案(独立 Dart 实现).md @@ -73,6 +73,10 @@ class Analytics { static Future setDeviceInfo(DeviceInfo deviceInfo); static Future flush(); + + // Phase 1: Lifecycle + static void bindLifecycleObserver({bool flushOnBackground = true, bool flushOnDetached = true}); + static void unbindLifecycleObserver(); static void setDebug(bool enabled); @@ -109,6 +113,8 @@ class AnalyticsConfig { this.maxRetryCount = 3, this.connectTimeout = const Duration(seconds: 5), this.readTimeout = const Duration(seconds: 5), + this.useIsolateStorage = true, // 默认开启 Isolate + this.maxEventAge = const Duration(days: 7), // 事件过期时间 }); } ``` @@ -137,6 +143,7 @@ lib/ storage/ event_storage.dart // 抽象接口 sqflite_event_storage.dart // SQLite 实现 + isolate_event_storage.dart // (New) Isolate 异步存储包装 network/ api_client.dart // 与后端 API 通信 diff --git a/3.Flutter todo list.md b/3.Flutter todo list.md index b0219ae..0145197 100644 --- a/3.Flutter todo list.md +++ b/3.Flutter todo list.md @@ -42,7 +42,7 @@ - [x] 实现 `track` 主流程(构造事件、入库、trim、达到 batchSize 触发 flush) - [x] 实现 `flush`(互斥、防并发、批量发送、重试与退避) - [x] 稳定性增强(重试退避、异常兜底、坏数据清理) -- [x] Phase 2 已接入(ConfigManager、Validator、配置周期刷新、release 校验标记) +- [x] Phase 2 已接入(ConfigManager、Validator、配置周期刷新、release 校验标记)\n- [x] 实现 `IsolateEventStorage`(默认启用,后台 Isolate 执行 IO)\n- [x] 实现生命周期监听(`bindLifecycleObserver`,后台/销毁时自动 flush) ### 5. Facade 对外接口(company_analytics.dart) diff --git a/README.md b/README.md index 465f1e9..b2d2e37 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ ## 功能特性 - 统一事件模型,自动补齐公共字段(systemCode、deviceInfo、时间戳等) -- 本地持久化队列(sqflite),断网可缓存,恢复后补发 +- 本地持久化队列(sqflite),默认运行在独立 Isolate 中,避免阻塞 UI +- 应用生命周期监听(进入后台/销毁时自动 flush) - 批量上报 + 重试退避 + 队列上限裁剪 - 配置下发(`GetSystemAllDimInfo`)与本地缓存 - 事件校验(Debug 详细日志,Release 自动标记 `_sdk_*`) @@ -35,6 +36,9 @@ Future bootstrapAnalytics() async { enableDebug: true, ), ); + + // 注册生命周期监听(推荐) + Analytics.bindLifecycleObserver(); } ``` @@ -57,7 +61,7 @@ await Analytics.flush(force: true); ## 关键配置项(AnalyticsConfig) 除了文档中的 Phase 1 配置项,还新增了以下能力配置: - +- `useIsolateStorage`: 是否使用 Isolate 进行存储操作(默认 `true`,强烈建议开启) - `enableMetrics`:是否启用 SDK 自监控指标(默认 `true`) - `metricsReportInterval`:指标上报周期(默认 10 分钟) - `blockOnValidationError`:Debug 下遇到校验 error 是否阻断发送(默认 `false`) diff --git a/analysis_options.yaml b/analysis_options.yaml index 050635f..fe1f972 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -4,5 +4,3 @@ analyzer: exclude: - coverage/** -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/lib/src/storage/isolate_event_storage.dart b/lib/src/storage/isolate_event_storage.dart index 4f816eb..8cf214a 100644 --- a/lib/src/storage/isolate_event_storage.dart +++ b/lib/src/storage/isolate_event_storage.dart @@ -327,6 +327,8 @@ Future _storageWorkerEntry(_WorkerInit init) async { } await storage.deleteByIds(ids.cast()); init.responsePort.send({ + 'id': id, + 'ok': true, 'result': null, }); case _msgCount: @@ -368,6 +370,8 @@ Future _storageWorkerEntry(_WorkerInit init) async { } await storage.updateRetryCount(idValue, retry); init.responsePort.send({ + 'id': id, + 'ok': true, 'result': null, }); case _msgDispose: