鸿蒙(HarmonyOS)应用开发实战——预渲染实现Web页面瞬开效果

238 篇文章 1 订阅
200 篇文章 0 订阅

往期知识点整理

介绍

为了便于大家在使用本案例集时能够更详细的了解各个案例,本案例基于Web预渲染实现了案例介绍功能,即应用右下角的问号icon。

效果图预览

使用说明

  1. 因为直接加载的线上README,因此本功能需联网使用
  2. 点击icon,即会弹出对应案例的README
  3. 按钮可拖动
  4. 返回或下拉bindSheet上方的dragBar可隐藏帮助页

案例适配说明

为确保案例正确显示其README,请确保entry模块的依赖中@ohos/xxx中的xxx与案例目录名相同

实现思路

  1. 使用Stack承载Navigation,从而使得icon能够在应用的各个案例(NavDestination承载)上显示。源码见EntryView.ets
    Stack() {
      Navigation(this.pageStack) {
      //...
      }
      // 帮助功能:在每个案例的右下角添加“帮助”功能
      HelperView()
    }
  1. 使用BindSheet+WebView加载仓上各模块README。
    build() {
      Image($r("app.media.help"))
        .bindSheet($$this.isShowReadMe, this.buildReadMeSheet(), {
          //...
      })
    }
    
    @Builder
    buildReadMeSheet(): void {
      //...
    }
    ```
1. 使用webview预渲染提升用户体验,复用webview实例减少资源占用。源码见[NWebUtils.ets](./src/main/ets/common/utils/NWebUtils.ets)
    ```typescript
    /**
     * Builder中为动态组件的具体组件内容
     * 调用onActive,开启渲染
     */
    @Builder
    function WebBuilder(data: Data) {
      Web({ src: data.url, controller: data.controller })
        .onPageBegin(() => {
          data.controller.onActive();
        })
        .width($r("app.string.full_size"))
        .height($r("app.string.full_size"))
    }
    
    
    const wrap: WrappedBuilder<Data[]> = wrapBuilder<Data[]>(WebBuilder);
    
    /**
     * 用于控制和反馈对应的NodeContainer上的节点的行为,需要与NodeContainer一起使用
     */
    export class NWebNodeController extends NodeController {
      private rootNode: BuilderNode<Data[]> | null = null;
    
      /**
       * 必须要重写的方法,用于构建节点数、返回节点挂载在对应NodeContainer中
       * 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新
       */
      makeNode(uiContext: UIContext): FrameNode | null {
        if (this.rootNode) {
          return this.rootNode.getFrameNode();
        }
        return null; // 返回null控制动态组件脱离绑定节点
      }
    
      /**
       * 自定义函数,可作为初始化函数使用
       * 通过UIContext初始化BuilderNode,再通过BuilderNode中的build接口初始化@Builder中的内容
       */
      initWeb(url: string, uiContext: UIContext, controller: WebviewController) {
        if (this.rootNode) {
          return;
        }
        // 创建节点与动态web组件
        this.rootNode = new BuilderNode(uiContext);
        this.rootNode.build(wrap, { url: url, controller: controller });
      }
    }
    
    interface CurrentNode {
      url: string | null;
      webController: webview.WebviewController | null;
      nWebController: NWebNodeController | null;
      lastNetAvailable: boolean;
    }
    
    /**
     * 复用webview
     */
    function loadUrl(url: string): void {
      if (currentNode.webController) {
        currentNode.url = url;
        currentNode.webController.loadUrl(url);
      }
    }
    
    // 当前的Node
    const currentNode: CurrentNode = { url: null, nWebController: null, webController: null, lastNetAvailable: true };
    
    /**
     * 销毁相关资源
     */
    export function clearHelperWeb() {
      currentNode.url = null;
      currentNode.webController = null;
      currentNode.nWebController = null;
    }
    
    /**
     * 创建web实例,如果已经存在web实例,复用
     * @param url
     * @param uiContext
     */
    export function createNWeb(url: string, uiContext: UIContext): void {
      if (currentNode.webController && currentNode.nWebController && currentNode.url !== url || !currentNode.lastNetAvailable) {
        loadUrl(url);
        currentNode.lastNetAvailable = connection.hasDefaultNetSync();
        return;
      }
      clearHelperWeb();
      let baseNode = new NWebNodeController();
      let controller = new webview.WebviewController();
      // 初始化自定义web组件
      baseNode.initWeb(url, uiContext, controller);
      currentNode.url = url;
      currentNode.webController = controller;
      currentNode.nWebController = baseNode;
      currentNode.lastNetAvailable = connection.hasDefaultNetSync();
    }
    
    /**
     * 获取NodeController
     */
    export function getNWeb(url: string): NWebNodeController | null {
      if (currentNode.url != url || !currentNode.lastNetAvailable) {
        loadUrl(url);
      }
      currentNode.lastNetAvailable = connection.hasDefaultNetSync();
      return currentNode.nWebController;
    }
    
    /**
     * 停止页面加载:当url频繁切换时使用
     */
    export function stopWebLoad(): void {
      if (currentNode.url && currentNode.webController) {
        currentNode.webController.stop();
      }
    }
    ```
1. 监听NavPathStack的变更,及时切换url。源码见[HelperView.ets](src/main/ets/pages/HelperView.ets)
    ```typescript
    onPageStackChange(): void {
      if (!this.pageStack.size()) {
        this.helperUrl = HelperConstants.HELPER_URL_HOME;
      } else {
        const size: number = this.pageStack.size();
        let moduleName: string = this.pageStack.getAllPathName()[size-1].split('/')[1];
        this.helperUrl = HelperConstants.HELPER_URL_PROTOTYPE.replace("{placeholder}", moduleName);
      }
    }

最后

总是有很多小伙伴反馈说:鸿蒙开发不知道学习哪些技术?不知道需要重点掌握哪些鸿蒙开发知识点? 为了解决大家这些学习烦恼。在这准备了一份很实用的鸿蒙全栈开发学习路线与学习文档给大家用来跟着学习。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植……等)技术知识点。

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

鸿蒙开发面试真题(含参考答案):

在这里插入图片描述

《OpenHarmony源码解析》:

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

图片

OpenHarmony 设备开发学习手册:https://gitcode.com/HarmonyOS_MN/733GH/overview

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值