#创作者激励# OpenHarmony启动页后记 原创

Tuer白晓明
发布于 2023-3-3 16:05
浏览
0收藏

【本文正在参加2023年第一期优质创作者激励计划】


1 回顾

通过DevEco Studio端云协同开发OpenHarmony/HarmonyOS应用程序(以下简称应用)集成AppGallery Connect(以下简称AGC)平台云函数云数据库云存储三篇文章笔者从创建端云协同应用程序开始,逐步对云函数、云数据库、云存储简单的数据读取做了简单的介绍。通过使用云数据库、云存储相结合的方式使应用的启动页能够动态化,即可以在不更新应用的情况下更改启动页的参数已达到启动页的动态化。

2 问题及解决方案

问题: 由于启动页参数来源于云数据库、云存储,启动页数据渲染前会受网络影响出现白屏。

解决方案: 为启动页数据单独封装获取方法,在启动页新增状态值,数据未加载完成后显示当前应用的icon图标,数据加载完成后渲染实际获取到的数据。

注: 若读者有其他的处理方法可与笔者共同探讨一下。

3 优化调用方法

使用async将函数异步化,使用await获取Promise的值。

3.1 云数据库获取数据方法异步化

每次使用存储区都要在使用完成后释放,新增关闭存储区方法。

// service/CloudDBService.ts
// @ts-ignore
import * as schema from './app-schema.json';
import { splash } from './splash';
import {
    AGConnectCloudDB,
    CloudDBZoneConfig,
    CloudDBZone,
    CloudDBZoneQuery
} from '@hw-agconnect/database-ohos';

import { AGCRoutePolicy } from '@hw-agconnect/core-ohos';

import { getAGConnect } from './AgcConfig';

export class CloudDBService {

    private static readonly ZONE_NAME = "cloudDBZoneSplash";
    private static cloudDB: AGConnectCloudDB;
    private static cloudDBZone: CloudDBZone;
    private static isInit: boolean;

    public static async init(context: any): Promise<boolean> {
        if (this.isInit) {
            return;
        }
        try {
            // 初始化agc
            getAGConnect(context);
            // 初始化Cloud DB
            await AGConnectCloudDB.initialize(context);
            // 获取对应数据处理位置的CloudDB实例
            this.cloudDB = await AGConnectCloudDB.getInstance(AGCRoutePolicy.CHINA);
            // 创建对象类型
            this.cloudDB.createObjectType(schema);
            // 打开存储区
            await this.openZone(this.ZONE_NAME);
            this.isInit = true;
        } catch (err) {
            console.error(JSON.stringify(err))
        }
        return Promise.resolve(this.isInit);
    }

    // 打开存储区
    private static async openZone(zoneName: string): Promise<CloudDBZone> {
        if (this.cloudDBZone) {
            return;
        }
        try {
            const cloudDBZoneConfig = new CloudDBZoneConfig(zoneName);
            this.cloudDBZone = await this.cloudDB.openCloudDBZone(cloudDBZoneConfig);
        } catch (err) {
            console.error(JSON.stringify(err));
        }
    }

    // 关闭存储区
    public static async closeZone(): Promise<void> {
        try {
            this.cloudDB.closeCloudDBZone(this.cloudDBZone);
            this.cloudDBZone = null;
        } catch (err) {
            console.error(JSON.stringify(err))
        }
    }

    public static async query(): Promise<splash> {
        try {
            const query = CloudDBZoneQuery.where(splash).equalTo("status", 1);
            const result = await this.cloudDBZone.executeQuery(query);
            return result.getSnapshotObjects().length > 0 ? result.getSnapshotObjects()[0] : new splash();
        } catch (err) {
            console.error(JSON.stringify(err));
        }
    }
}

3.2 云存储获取数据方法异步化

// services/cloudstorage/CloudStorageService.ts
import agconnect from '@hw-agconnect/api-ohos';
import "@hw-agconnect/cloudstorage-ohos";

import { getAGConnect } from '../AgcConfig';

export class CloudStorageService {

    public static async init(context: any, path: string): Promise<string> {
        try {
            getAGConnect(context);
            // 初始化默认实例
            const storage = agconnect.cloudStorage();
            // 创建需要下载文件的引用
            const storageReference = await storage.storageReference();
            var reference = await storageReference.child(path);
            return reference.getDownloadURL();
        } catch (err) {
            console.error(JSON.stringify(err));
        }
    }
}

4 为启动页数据获取封装专用方法

可以将一些处理逻辑放在该方法中处理。

// services/SplashService.ts
import { splash } from './splash';
import { CloudDBService } from '../services/CloudDBService';
import { CloudStorageService } from '../services/cloudstorage/CloudStorageService';

export class SplashService {

    public static async querySplash(context: any): Promise<splash> {
        try {
            await CloudDBService.init(context);
            let splash = await CloudDBService.query();
            let url = await CloudStorageService.init(context, splash.backgroundImg);
            splash.backgroundImg = url;
            await CloudDBService.closeZone();
            return splash;
        } catch (err) {
            console.error(JSON.stringify(err));
        }
    }
}

5 改写启动页

启动页新增状态码,用于数据未加载完成呈现给用户的显示界面,规避数据未获取导致的白屏现象。

@State isSkip: boolean = false;

aboutToAppear()方法中执行获取启动页数据的方法。

  aboutToAppear() {
    this.isSkip = false;
    SplashService.querySplash(getContext(this)).then((ret) => {
      this.isSkip = true;
      this.result = ret;
    })
  }

页面中使用if(){}else{}条件语句判断渲染的组件,从而规避数据请求时间导致的白屏。

if (this.isSkip) {
  SplashPage({ mSplash: {
    timer: this.result.timer,
    isLogo: this.result.isLogo,
    backgroundImg: this.result.backgroundImg,
    companyName: this.result.companyName,
    mFontColor: this.result.mFontColor
  }, skip: this.onSkip })
} else {
  Column() {
    Image($r('app.media.icon')).objectFit(ImageFit.None)
  }
  .width('100%').height('100%')
}

通过更改AGC平台云数据库中启动页数据状态,可以实现下次启动应用程序,启动页呈现不同内容。使用场景如新闻类App可以在启动页呈现一条配备图片的热文;常规App可以在启动页呈现一条经典语录;实现不同节日在启动页呈现问候信息。

7 后记

本文所记为之前文章的总结,针对获取AGC平台各项服务的数据,可直接调用对应的方法即可。若出现复杂的情况,如后面笔者将实现认证服务登录,并将用户信息存储到云数据库中,可以结合云函数,在用户登录的时候,直接调用云函数去保存用户信息,存储方法可以通过云函数的AUTH触发器实现数据存储云数据库中;再如用户上传图片,生成缩略图,也可以利用云函数将原图和缩略图一同保存到云存储中。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
1
收藏
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

有始有终,为白老师点赞

已于2023-3-3 18:41:05修改
回复
2023-3-3 18:40:51
回复
    相关推荐