<

{{title}}

{{file.summary.functions.pct}}%

Functions
{{file.summary.functions.covered}}/{{file.summary.functions.total}}

{{file.summary.branches.pct}}%

Branches
{{file.summary.branches.covered}}/{{file.summary.branches.total}}

{{file.summary.lines.pct}}%

Lines
{{file.summary.lines.covered}}/{{file.summary.lines.total}}
          
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2x
2x
2x
 
2x
 
 
 
 
 
 
 
 
 
5x
5x
5x
 
5x
 
 
5x
4x
4x
4x
3x
 
 
 
 
4x
4x
3x
3x
 
 
 
 
3x
2x
 
 
 
 
 
 
 
3x
3x
3x
3x
 
 
 
 
 
 
 
 
 
                
import webview from '@ohos.web.webview'; 
 
/** 
 * 渲染进程异常后的页面恢复策略。 
 * 
 * 渲染进程被系统回收后 Web 组件不会自动恢复,需主动重载,否则页面卡死/白屏。 
 * 恢复链:`loadUrl(fallbackUrl)` → `refresh()` → `onUnrecoverable()`。 
 * 
 * **为何 loadUrl 优先于 refresh**:进程崩溃后内部状态未清,`refresh()`/`reload()` 常失效 
 * (甚至不抛错却也未真正恢复),`loadUrl()` 能强制重建渲染管线。与 Android(新建实例后 loadUrl)、 
 * iOS(优先 load(URLRequest))对齐,亦符合社区推荐。 
 * 
 * **延迟恢复**:崩溃后立即 reload 可能因内存/资源仍紧张而再次崩溃(尤其 OOM 场景), 
 * 故延迟 `RECOVER_DELAY_MS` 再执行,给系统留出资源回收窗口(对齐社区实践)。 
 */ 
export class RenderRecovery { 
  /** 崩溃后延迟恢复的毫秒数,避免瞬间抢占资源再次崩溃。 */ 
  private static readonly RECOVER_DELAY_MS: number = 1000; 
 
  /** 
   * 尝试恢复 Web 组件(延迟 `RECOVER_DELAY_MS` 后执行,避免瞬间再次崩溃)。 
   * 
   * **重要**:返回的 timer id 必须由调用方保存,并在容器销毁/归还池时 `clearTimeout` 取消, 
   * 否则延迟窗口内用户关闭页面后,回调仍会访问已销毁/已归还的 controller,导致无效 reload 
   * 或污染已归还的池实例(野指针)。 
   * 
   * @param controller WebviewController 
   * @param fallbackUrl 优先用以 `loadUrl` 重载的 URL;空串表示无可用 URL(退化为 `refresh` 兜底) 
   * @param onUnrecoverable 全部尝试失败时的回调(如关闭容器) 
   * @returns 延迟恢复的 timer id,供调用方在生命周期结束时 `clearTimeout` 取消 
   */ 
  public static recover( 
    controller: webview.WebviewController, 
    fallbackUrl: string, 
    onUnrecoverable?: () => void 
  ): number { 
    return setTimeout(() => { 
      RenderRecovery.performRecover(controller, fallbackUrl, onUnrecoverable); 
    }, RenderRecovery.RECOVER_DELAY_MS); 
  } 
 
  /** 
   * 立即执行一次恢复尝试(同步)。恢复链:`loadUrl(fallbackUrl)` → `refresh()` → `onUnrecoverable()`。 
   * 供 {@link recover} 延迟调度调用,亦便于单测同步验证。 
   */ 
  public static performRecover( 
    controller: webview.WebviewController, 
    fallbackUrl: string, 
    onUnrecoverable?: () => void 
  ): void { 
    // 优先 loadUrl(fallbackUrl):进程崩溃后 refresh() 常因内部状态未清而失效,loadUrl 能强制重建渲染管线 
    // (与 Android/iOS 恢复方式对齐,符合社区推荐)。 
    if (fallbackUrl.length > 0) { 
      try { 
        controller.loadUrl(fallbackUrl); 
        return; 
      } catch (_e) { 
        // fallthrough:loadUrl 失败再退化尝试 refresh 兜底 
      } 
    } 
    // 无可用 URL / loadUrl 失败 → 退化尝试 refresh;仍失败则判定不可恢复(触发关闭容器)。 
    try { 
      controller.refresh(); 
    } catch (_e) { 
      RenderRecovery.fireUnrecoverable(onUnrecoverable); 
    } 
  } 
 
  private static fireUnrecoverable(cb?: () => void): void { 
    if (cb !== undefined) { 
      cb(); 
    } 
  } 
 
  /** 
   * 从 `onPageBegin` 事件中提取主框架 URL,用于 `recover()` 的 fallback 兜底。 
   * 提取失败返回 `current`,不覆盖原值。 
   */ 
  public static captureLastUrl(event: ESObject, current: string): string { 
    try { 
      const url: string = (event as ESObject).url as string; 
      return (url !== null && url !== undefined && url.length > 0) ? url : current; 
    } catch (_e) { 
      return current; 
    } 
  } 
 
  private constructor() {} 
} 

              
Code coverage generated by bjc at {{date}}