当前位置: 首页 > backend >正文

鸿蒙5.0项目开发——鸿蒙天气项目的实现(欢迎页)

【高心星出品】

文章目录

      • 欢迎页面效果
      • 数据字典
      • 创建数据库表格
      • Splash页面
        • 页面功能
        • 欢迎页代码
        • 亮点

项目按照从数据库连接层–视图层–业务逻辑层这种三层架构开发,所以先设计了数据库表格的结构,在EntryAbility中创建表格。

欢迎页面效果

在这里插入图片描述

数据字典

  • searchmodel的数据字典:
/***** 搜索历史记录模型*** 用于存储用户搜索关键词的历史记录***/*export interface SearchHistoryItem {id?: number     *// 记录ID,可选*keyword: string   *// 搜索关键词*timestamp?: string  *// 搜索时间戳,可选*}
  • adcode的数据字典:
/***** 城市编码模型*** 用于存储城市相关的编码信息***/*export interface adcode {id: number      *// 城市ID*pid?: number     *// 父级ID,可选*city_code: string  *// 城市编码*city_name: string  *// 城市名称*post_code?: string  *// 邮政编码,可选*area_code?: string  *// 区号,可选*ctime?: string    *// 创建时间,可选*}

这两个模型的主要用途:

SearchHistoryItem:

  • 用于记录用户的搜索历史

  • 包含搜索关键词和时间信息

  • 可用于实现搜索历史功能

adcode:

  • 用于存储城市信息

  • 包含城市编码、名称等基本信息

  • 支持城市层级关系(通过pid)

  • 包含邮政和区号等附加信息

创建数据库表格

编写DbUtils实现对于表格的创建。

  • 创建名为 weatherinfo.db 的数据库

  • 设置数据库安全级别为 S1

  • 初始化两个数据表:

  • t_adcode:存储城市信息

  • t_search:存储搜索历史

import { relationalStore } from "@kit.ArkData";/***作者:gxx*时间:2025/4/21 9:16*功能:数据库操作**/
// 城市编码表名
export const TABLENAME: string = 't_adcode'// 搜索历史表名
export const TABLENAME1: string = 't_search'// 数据库配置
const CONFIG: relationalStore.StoreConfig = {name: 'weatherinfo.db', // 数据库名称securityLevel: relationalStore.SecurityLevel.S1 // 安全级别
}/*** 获取数据库实例* @param context 上下文对象* @returns 数据库实例*/
export async function getrdb(context: Context) {return relationalStore.getRdbStore(context, CONFIG)
}/*** 创建数据库表* @param context 上下文对象* @description 创建城市编码表和搜索历史表*/
export async function createtable(context: Context) {try {// 创建城市编码表SQL语句let sql = 'CREATE TABLE IF NOT EXISTS t_adcode (\n' +'    id INTEGER PRIMARY KEY AUTOINCREMENT,\n' + // 自增主键'name TEXT NOT NULL,    code VARCHAR(50) NOT NULL,\n' + // 城市名称和编码'    city VARCHAR(50) \n' + // 所属城市');'// 创建搜索历史表SQL语句let sql1 = 'CREATE TABLE IF NOT EXISTS t_search (\n' +'  id INTEGER PRIMARY KEY AUTOINCREMENT,\n' + // 自增主键'keyword TEXT NOT NULL,    timestamp VARCHAR(50) NOT NULL);' // 搜索关键词和时间戳// 获取数据库实例并执行SQLlet rdb = await getrdb(context)rdb.executeSync(sql)rdb.executeSync(sql1)} catch (e) {console.error('dbutils 创建表格失败: ', JSON.stringify(e))}
}

在EntryAbility中创建表格。

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { createtable } from '../utils/Dbutils';const DOMAIN = 0x0000;export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');}onDestroy(): void {hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');}async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {// 1. 记录窗口创建日志hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');// 2. 创建数据库表格// 创建adcode和search_history两个表格用于存储城市代码和搜索历史await createtable(this.context)// 3. 加载启动页面// 加载splash页面,splash页面会检查是否已导入城市数据// 如果未导入则会从cityma.txt读取并导入数据库// 导入完成后跳转到主页面IndexwindowStage.loadContent('pages/splash', async (err) => {if (err.code) {// 4. 加载失败处理hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));return;}// 5. 加载成功记录hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');});}onWindowStageDestroy(): void {// Main window is destroyed, release UI related resourceshilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');}
}

Splash页面

页面功能

1.数据初始化:

  • 页面启动时会检查是否已经加载过城市数据(通过 PreferenceUtils 存储的 isload 标志)

  • 如果数据未加载,会执行 charu 函数来初始化数据

2.charu 函数的具体工作:

  • 从资源文件中读取 cityma.txt(城市码数据文件)

  • 将文件内容解析为 JSON 数据

  • 通过 adcodedao 将城市数据插入到数据库中

  • 使用 @Concurrent 注解确保在后台线程执行,避免阻塞主线程

3.界面展示:

  • 显示一个启动图片

  • 展示一个环形进度条动画

  • 显示"加载中…"文字

4.页面跳转:

  • 数据加载完成后,会自动跳转到主页面(pages/Index)
欢迎页代码
import { adcodedao } from '../dao/adcodedao';
import { buffer, taskpool } from '@kit.ArkTS';
import { common } from '@kit.AbilityKit';
import { adcode } from '../model/adcode';
import { PreferenceUtils } from '../utils/PreferenceUtils';
import { router } from '@kit.ArkUI';/*** 插入城市数据到数据库* @param context 上下文对象* @returns 插入是否成功*/
@Concurrent
async function charu(context: Context) {try {// 创建数据访问对象let ad = new adcodedao(context)// 读取原始文件内容let value = await context.resourceManager.getRawFileContent('cityma.txt')// 转换为字符串let data = buffer.from(value).toString()// 解析JSON数据let content = JSON.parse(data) as adcode[]// 插入数据库await ad.insert(content)return true} catch (e) {console.error('gxxt ', JSON.stringify(e))return false}
}// 持久化存储的key名称
const Prename: string = 'loaded'/*** 启动页面组件*/
@Entry
@Component
struct Splash {@State message: string = 'Hello World';// 进度条值@State value: number = 10// 上下文对象private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext// 定时器IDprivate intervalid: number = 0/*** 组件即将出现时的生命周期函数*/aboutToAppear(): void {// 设置定时器更新进度条this.intervalid = setInterval(() => {if (this.value == 100) {this.value = -10}this.value += 10}, 100)// 检查是否已加载过数据let loaded = PreferenceUtils.getInstance(this.context, Prename).get('isload', false) as booleanif (loaded) {// 如果已加载过数据,直接跳转到主页router.replaceUrl({ url: 'pages/Index' })} else {// 如果未加载过数据,则读取文件并插入数据库taskpool.execute(charu, this.context).then((value) => {// 保存加载状态PreferenceUtils.getInstance(this.context, Prename).putfile('isload', value as boolean)// 跳转到主页router.replaceUrl({ url: 'pages/Index' })})}}/*** 构建UI界面*/build() {Stack() {// 背景图片Image($r('app.media.splash'))// 进度条Progress({ value: this.value, total: 100, type: ProgressType.ScaleRing }).width(100).height(100).backgroundColor(Color.Black).style({ strokeWidth: 15, scaleCount: 20, scaleWidth: 5 }).color(Color.White)// 加载提示文本Text('加载中...').fontWeight(FontWeight.Bolder)}.height('100%').width('100%').alignContent(Alignment.Center)}/*** 组件即将消失时的生命周期函数*/aboutToDisappear(): void {// 清除定时器clearInterval(this.intervalid)}
}
亮点

1.使用多线程将大量数据批量插入数据库

批量插入:

 /*** 批量插入城市数据到数据库* @param acs 城市数据数组* @description 将城市数据批量插入到数据库中* 如果城市数据包含ctime字段,则插入name、code、city三个字段* 否则只插入name和code两个字段*/async insert(acs: adcode[]) {try {// 获取数据库实例let rdb = await getrdb(this.context)// 存储要插入的数据let values: relationalStore.ValuesBucket[] = []// 遍历城市数据acs.forEach((ac: adcode) => {let value: relationalStore.ValuesBucket// 判断是否有ctime字段if (ac.ctime) {value = {'name': ac.city_name, // 城市名称'code': ac.city_code, // 城市编码'city': ac.ctime // 所属城市}} else {value = {'name': ac.city_name, // 城市名称'code': ac.city_code, // 城市编码}}values.push(value)})// 批量插入数据rdb.batchInsertSync(TABLENAME, values)} catch (e) {console.error('gxxt adcodedao 插入数据错误: ', e.message)}}

多线程运行实体:

@Concurrent
async function charu(context: Context) {try {// 创建数据访问对象let ad = new adcodedao(context)// 读取原始文件内容let value = await context.resourceManager.getRawFileContent('cityma.txt')// 转换为字符串let data = buffer.from(value).toString()// 解析JSON数据let content = JSON.parse(data) as adcode[]// 插入数据库await ad.insert(content)return true} catch (e) {console.error('gxxt ', JSON.stringify(e))return false}
}

多线程执行:

 // 如果未加载过数据,则读取文件并插入数据库taskpool.execute(charu, this.context).then((value) => {// 保存加载状态PreferenceUtils.getInstance(this.context, Prename).putfile('isload', value as boolean)// 跳转到主页router.replaceUrl({ url: 'pages/Index' })})

2.使用Interval配合环形刻度进度条来制作动态的加载动画

 // 设置定时器更新进度条this.intervalid = setInterval(() => {if (this.value == 100) {this.value = -10}this.value += 10}, 100)
....................................// 进度条Progress({ value: this.value, total: 100, type: ProgressType.ScaleRing }).width(100).height(100).backgroundColor(Color.Black).style({ strokeWidth: 15, scaleCount: 20, scaleWidth: 5 }).color(Color.White)
http://www.xdnf.cn/news/6155.html

相关文章:

  • React构建组件
  • Android学习总结之Glide自定义三级缓存(面试篇)
  • 网络实验-GRE
  • QT-1.信号与槽
  • HarmonyOS NEXT~React Native在鸿蒙系统(HarmonyOS)上的适配现状与技术展望
  • 【论文阅读】UNIT: Backdoor Mitigation via Automated Neural Distribution Tightening
  • CMD(Command Prompt)和 Anaconda 的不同
  • Mathematics-2025《Semi-Supervised Clustering via Constraints Self-Learning》
  • 查询电脑伪装IP,网络安全速查攻略!
  • 入门OpenTelemetry——可观测性与链路追踪介绍
  • Nginx核心功能及同类产品对比
  • FastByteArrayOutputStream和ByteArrayInputStream有什么区别
  • 基于javaweb的SpringBoot高校图书馆座位预约系统设计与实现(源码+文档+部署讲解)
  • package-lock.json能否直接删除?
  • 【Ansible基础】Ansible设计理念与无代理架构深度解析
  • 2020年下半年试题三:论云原生架构及其应用
  • SAP学习笔记 - 开发11 - RAP(RESTful Application Programming)简介
  • 鸿蒙OSUniApp开发富文本编辑器组件#三方框架 #Uniapp
  • 鸿蒙OSUniApp 制作个人信息编辑界面与头像上传功能#三方框架 #Uniapp
  • 计算机网络的七层“千层饼“
  • TCP/IP参考模型详解:从理论架构到实战应用
  • 牛市买卖数字货币逻辑
  • Java 中序列化和反序列化的详细说明
  • Android学习总结之类LiveData与ViewModel关系篇
  • 【Redis 进阶】分布式锁
  • Q1财报揭示:用户增长与客单价下跌对eBay卖家的蝴蝶效应
  • 最佳实践PPT | 数据架构设计总体规划方案数据中台架构数据架构图解决方案
  • 深度解析智能体:从概念到应用的全方位洞察
  • AI产品上市前的“安全通行证“
  • 7.DTH11和PWM波