review: M3+M4 成果审查后的质量加固

八角度审查 15 Provider+微信/七牛+双容器+导航。桥核心/契约骨架基本无误;修确凿问题:

正确性/健壮性
- ShakeProvider:stop()/onDestroy 取消未决 shakeEnd 计时并复位 pending(修停止后仍触发出站、重启后首摇被吞、计时器泄漏)
- VibrateProvider:startRepeat 先 stopRepeat(修重复 repeatvibrator('1') 叠加出无法取消的孤儿计时链)
- PhotoProvider:JSON.parse 后 Array.isArray 守卫(修 H5 传非数组致 .map 抛错、出站永不下发使 H5 挂死);去不可达 .catch
- GenericWebContainer:getWebdata 直调改用 JSON.stringify 生成 JS 字符串实参(修 data 含换行/行分隔符断行致注入语法错误)
- LocationProvider:单次请求前先停连续监听(修连续后切单次仍持续推送);去 push() 中 !continuousOn→stopContinuous 死代码

加固/清理
- BridgeGameContainer:抽 firstReadyPush() 幂等助手(appservice/setPostUrl/pendingWebdata);保持 100% 触发时序
  (注明为何用 100% 而非更早 onPageEnd:确保 H5 已注册 handler);aboutToDisappear 置空 hostCtx/config/resource

研判驳回(与原 Android 一致/契约默认/自愈):getphonestate CallState 值映射、通用容器 orientation 默认横屏、setMuted prepared 自愈、exitDialog backgameData() 无参通知。
延期(随微信集成):WeChatApi 单例陈旧回调/instanceof(容器重建后回调打旧 bridge;微信运行期本就待开放平台注册)。
记录待重构:AbstractProvider 基类 + parseJson 助手(去 15 Provider 重复 bridge/ctx/解析样板)、AVPlayer 复用、openBrowser/orientation 抽公共。

devecocli build 通过;单测通过;模拟器复测桥往返/appservice/setPostUrl 无回归。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-25 21:30:06 +08:00
parent 6bd0cf7488
commit 6bec98d584
25 changed files with 54 additions and 25 deletions
@@ -53,6 +53,27 @@ export struct BridgeGameContainer {
this.registrar = undefined;
this.bridge = undefined;
this.adapter = undefined;
this.hostCtx = undefined;
this.config = undefined;
this.resource = undefined;
}
/** 页面进度首次 100% 时下发 appservice/setPostUrl+子游戏返回大厅待发的 getWebdata)。幂等。
* firstProgressDone 在子游戏切换/返回大厅时复位,使重载后再次下发。 */
private firstReadyPush(): void {
if (this.firstProgressDone) {
return;
}
this.firstProgressDone = true;
const b = this.bridge;
if (b !== undefined) {
b.callHandler(OutboundHandlers.AppService, '1');
b.callHandler(OutboundHandlers.SetPostUrl, this.uploadServer.baseUrl());
if (this.pendingWebdata !== undefined) {
b.callHandler(OutboundHandlers.GetWebData, this.pendingWebdata);
this.pendingWebdata = undefined;
}
}
}
/** onControllerAttached:建桥 + 经组装根注册全部能力(框架 §A.1)。 */
@@ -197,19 +218,11 @@ export struct BridgeGameContainer {
this.bridge?.onPageEnd();
})
.onProgressChange((event: OnProgressChangeEvent) => {
if (event.newProgress === 100 && !this.firstProgressDone) {
// 首次/每次切换后页面到 100% → 推 appservice(前台) + setPostUrl(对齐 Android onProgressChanged==100
this.firstProgressDone = true;
const b = this.bridge;
if (b !== undefined) {
b.callHandler(OutboundHandlers.AppService, '1');
b.callHandler(OutboundHandlers.SetPostUrl, this.uploadServer.baseUrl());
}
// 子游戏返回大厅的回传数据,待大厅重载完成后下发 getWebdata
if (this.pendingWebdata !== undefined) {
b?.callHandler(OutboundHandlers.GetWebData, this.pendingWebdata);
this.pendingWebdata = undefined;
}
// 首次/每次切换后页面到 100% → 推 appservice(前台)+setPostUrl(对齐 Android onProgressChanged==100)。
// 用 100%(而非更早的 onPageEnd):确保 H5 在 WebViewJavascriptBridgeReady 里已注册 appservice/setPostUrl
// 等 handler,避免出站早于注册被丢。loadUrl 切子游戏/返回大厅会再次产生 100% 回调(已复位 firstProgressDone)。
if (event.newProgress === 100) {
this.firstReadyPush();
}
})
}