##鸿蒙核心技术##运动开发#

在开发鸿蒙运动项目时,管理不同运行环境(如开发环境、测试环境、生产环境)是一个常见的需求。通过合理地切换运行环境,开发者可以方便地进行调试、测试和部署。本文将介绍如何实现一个项目运行环境切换器,帮助你在鸿蒙开发中高效地管理不同环境的配置。

前言

在现代软件开发中,环境管理是确保应用稳定性和可维护性的关键环节之一。无论是开发、测试还是生产环境,每个环境都可能有不同的配置需求,例如 API 地址、日志级别、功能开关等。通过实现一个运行环境切换器,我们可以轻松地在不同环境之间切换,而无需修改代码,从而提高开发效率和灵活性。
在这里插入图片描述

一、环境切换器的设计

(一)环境配置类型

为了支持不同环境的配置,我们定义了 EnvironmentConfigsCurrentEnvironment 类型。

export type EnvironmentConfigs = Map<string, Map<string, string>>;export interface CurrentEnvironment {name: string;configs: Map<string, string>;
}

核心点解析

  1. EnvironmentConfigs:一个映射表,键为环境名称(如 productiondevelopment),值为该环境的配置映射表。
  2. CurrentEnvironment:表示当前环境的名称和配置。

(二)环境类型枚举

我们通过枚举定义了支持的环境类型。

export enum EnvironmentType {TYPE_PRODUCTION = "production",TYPE_DEVELOP = "develop"
}

核心点解析

  1. 枚举类型:通过枚举定义了两种环境类型:生产环境(production)和开发环境(develop)。可以根据需要扩展更多环境类型。

(三)环境管理类

环境管理类 Environment 是整个环境切换器的核心。它负责存储环境配置、加载保存的环境、切换环境以及通知回调。

export class Environment {private static instance: Environment;private static readonly ENVIRONMENT_STORAGE_KEY = 'current_environment';private currentEnvironment?: CurrentEnvironment;private environments: EnvironmentConfigs = new Map();private preferences: LibPreferencesSync;private environmentChangeCallbacks: Array<(newEnvironment: CurrentEnvironment) => void> = [];private constructor() {this.preferences = new LibPreferencesSync();}public static getInstance(): Environment {if (!Environment.instance) {Environment.instance = new Environment();}return Environment.instance;}public initEnvironments(evn: EnvironmentConfigs) {this.environments = evn;this.loadSavedEnvironment();}private loadSavedEnvironment() {if (!IS_PRODUCTION) {const savedEnvironmentName = this.preferences.getValue(Environment.ENVIRONMENT_STORAGE_KEY) as string;if (savedEnvironmentName && this.environments.has(savedEnvironmentName)) {this.currentEnvironment = {name: savedEnvironmentName,configs: this.environments.get(savedEnvironmentName)!};} else {this.currentEnvironment = {name: EnvironmentType.TYPE_DEVELOP,configs: this.environments.get(EnvironmentType.TYPE_DEVELOP)!};}} else {this.currentEnvironment = {name: EnvironmentType.TYPE_PRODUCTION,configs: this.environments.get(EnvironmentType.TYPE_PRODUCTION)!};}}public switchEnvironment(name: string) {const configs = this.environments.get(name);if (configs) {this.currentEnvironment = { name, configs };this.preferences.saveKeyValue(Environment.ENVIRONMENT_STORAGE_KEY, name);this.environmentChangeCallbacks.forEach(callback => callback(this.currentEnvironment!));}}public getCurrentEnvironment(): CurrentEnvironment {return this.currentEnvironment!;}public getAllEnvironmentNames(): string[] {return Array.from(this.environments.keys());}public registerEnvironmentChangeCallback(callback: (newEnvironment: CurrentEnvironment) => void) {this.environmentChangeCallbacks.push(callback);}public unregisterEnvironmentChangeCallback(callback: (newEnvironment: CurrentEnvironment) => void) {this.environmentChangeCallbacks = this.environmentChangeCallbacks.filter(cb => cb !== callback);}
}

核心点解析

  1. 单例模式:通过 getInstance 方法确保 Environment 的全局唯一性。
  2. 环境初始化:通过 initEnvironments 方法初始化环境配置。
  3. 加载保存的环境:在 loadSavedEnvironment 方法中,根据存储的环境名称加载对应的环境配置。
  4. 环境切换:通过 switchEnvironment 方法切换环境,并通知所有注册的回调函数。
  5. 回调机制:支持注册和注销环境切换回调,方便在环境切换时执行相关操作。

二、环境切换器的使用

(一)环境切换对话框

为了方便用户切换环境,我们实现了一个环境切换对话框 EnvironmentDialog

@CustomDialog
export struct EnvironmentDialog {public controller: CustomDialogController;private themeManager: ThemeManager = ThemeManager.getInstance();private environment: Environment = Environment.getInstance();public onEnvironmentChanged?: () => void;build() {Column() {Text('选择环境').fontSize(20).fontWeight(FontWeight.Bold).fontColor(this.themeManager.getTextPrimaryColor()).margin({ top: 24, bottom: 16 })List() {ForEach(this.environment.getAllEnvironmentNames(), (envname: string) => {ListItem() {Row() {Column() {Text(envname).fontSize(16).fontColor(this.themeManager.getTextPrimaryColor()).margin({ bottom: 4 })}.alignItems(HorizontalAlign.Start).layoutWeight(1)if (this.environment.getCurrentEnvironment().name === envname) {Image($r('app.media.base_icon_select')).width(24).height(24).margin({ left: 8 })}}.width('100%').padding(16).backgroundColor(this.themeManager.getSurfaceColor()).borderRadius(8).onClick(() => {this.environment.switchEnvironment(envname);this.onEnvironmentChanged?.();this.controller.close();})}.margin({ bottom: 8 })}, (envname: string) => envname)}.width('100%').layoutWeight(1)Button('关闭').width('100%').height(48).backgroundColor(this.themeManager.getPrimaryColor()).margin({ top: 16 }).onClick(() => {this.controller.close();})}.width('90%').padding(16).backgroundColor(this.themeManager.getBackgroundColor()).borderRadius(16)}
}

核心点解析

  1. 环境列表:通过 ForEach 遍历所有环境名称,并为每个环境生成一个列表项。
  2. 当前环境标识:如果当前环境与列表项环境一致,则显示选中图标。
  3. 环境切换:点击列表项时,调用 switchEnvironment 方法切换环境,并关闭对话框。
  4. 回调通知:环境切换后,调用 onEnvironmentChanged 回调函数,通知外部环境已切换。

(二)环境切换的回调机制

为了在环境切换时执行相关操作,我们可以通过注册回调函数来实现。

const environment = Environment.getInstance();environment.registerEnvironmentChangeCallback((newEnvironment) => {console.log(`环境已切换到: ${newEnvironment.name}`);// 在这里执行环境切换后的相关操作,例如重新加载配置、刷新界面等
});

核心点解析

  1. 注册回调:通过 registerEnvironmentChangeCallback 方法注册回调函数。
  2. 回调执行:在环境切换时,回调函数会被自动调用。

三、总结

通过实现一个项目运行环境切换器,我们可以在鸿蒙运动项目中轻松地管理不同环境的配置。环境切换器不仅支持动态切换环境,还提供了回调机制,方便在环境切换时执行相关操作。通过这种方式,开发者可以在开发、测试和生产环境中快速切换,而无需修改代码,从而提高开发效率和灵活性。

在实际开发中,你可以根据项目的具体需求,进一步扩展和优化环境切换器。例如:

  • 支持更多环境类型:根据项目需求,扩展更多环境类型,如测试环境、预发布环境等。
  • 动态加载配置:从远程服务器动态加载环境配置
  • 集成到构建工具:将环境切换器集成到构建工具中,支持在构建时指定运行环境。

希望本文能为你的鸿蒙开发之旅提供有价值的参考!如果你有任何问题或建议,欢迎随时交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/85788.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/85788.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/85788.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核中安全创建套接字:为何inet_create未导出及正确替代方案

引言 在Linux内核开发中,当驱动程序需要创建网络套接字时,开发者常会遇到一个关键问题:核心函数inet_create(负责初始化IPv4套接字)并未导出到内核符号表。本文深入剖析这一设计决策背后的逻辑,并提供驱动程序安全创建套接字的实践方案。 一、inet_create未导出的深层原…

63、不同路径II

题目 解答&#xff1a; 初始化和特殊情况比较麻烦的dp obstacleGrid(0,0)1的&#xff0c;直接return 0即可。入口都被堵住了还怎么走。 mn1情况&#xff0c;直接判断 第一行初始化&#xff1a;dp[1][0]->dp[i][0] 碰到有障碍物的&#xff0c;从当前格子开始到末尾全部置…

wx小程序登录设置角色

背景。pc端登录后在访问业务链接时可以根据固定获取用户的方法LoginUser user LoginHelper.getLoginUser(); 获取到用户信息。但wx端登录后无法获取。原因处在登陆时对用户信息的设置方面pc端和小程序端登录没有使用相同的登录方法。排除得知wx端小程序登录时没有设置角色。所…

MySQL5.7 慢查询SQL语句集合

文章目录 1. 按平均执行时间排序的慢查询2. 按总执行时长排序的慢查询3. MySQL 5.7 慢查询配置检查4. 扫描行数分析&#xff08;找出全表扫描&#xff09;5. 高频执行的慢查询6. 当前正在执行的查询7. 慢查询统计汇总8. 表结构和索引分析8.1 表索引详情查询8.2 表大小统计 1. 按…

MySQL学习(1)——基础库操作

欢迎来到博主的专栏:MySQL学习 博主ID:代码小豪 文章目录 数据库原理基础库操作增删数据库数据库编码与校验规则验证不同的校验规则对于库中数据的影响 备份与恢复数据库 数据库原理 mysql版本:mysql8.0 操作系统:ubuntu22.4 为了减少由于环境配置以及权限限制带来的使用问题&…

C++法则12:右值引用的核心目的:支持移动语义(Move Semantics)

C法则12&#xff1a;右值引用的核心目的&#xff1a;支持移动语义&#xff08;Move Semantics&#xff09; 右值引用&#xff08;Rvalue Reference&#xff09;是C11引入的最重要特性之一&#xff0c;其主要设计目的就是支持移动语义&#xff08;Move Semantics&#xff09;。 …

【LLM学习笔记4】使用LangChain开发应用程序(上)

目录 前言一、模型、提示和解析器&#xff08;model、prompt、parsers&#xff09;二、储存三、模型链四、基于文档的问答1.使用向量存储查询2. 结合表征模型和向量存储使用检索问答链回答问题 前言 在前面两部分&#xff0c;我们分别学习了大语言模型的基础使用准则&#xff…

Negative Contrastive Estimation Negative Sampling

1. 基本概念与问题背景 1.1 大规模分类问题 在自然语言处理中&#xff0c;给定上下文 c c c预测单词 w w w的条件概率为&#xff1a; P ( w ∣ c ) exp ⁡ ( s θ ( w , c ) ) ∑ w ′ ∈ V exp ⁡ ( s θ ( w ′ , c ) ) P(w|c) \frac{\exp(s_\theta(w,c))}{\sum_{w\in V…

Flink SQL Connector Kafka 核心参数全解析与实战指南

Flink SQL Connector Kafka 是连接Flink SQL与Kafka的核心组件&#xff0c;通过将Kafka主题抽象为表结构&#xff0c;允许用户使用标准SQL语句完成数据读写操作。本文基于Apache Flink官方文档&#xff08;2.0版本&#xff09;&#xff0c;系统梳理从表定义、参数配置到实战调优…

vscode内嵌浏览器实时预览vue项目

安装插件 web Preview 启动vue项目 打开预览 ctrl shift p 之后输入并选择 Open Web Preview 即可看到预览窗口&#xff0c;但此时明明我的页面是有内容的&#xff0c;但是窗口却空白的。 因为默认访问端口是3000&#xff0c;我们将其修改为vue项目默认的5173端口即可。 点…

计算机网络:(四)物理层的基本概念,数据通信的基础知识,物理层下面的传输媒体

计算机网络&#xff1a;&#xff08;四&#xff09;物理层的基本概念&#xff0c;数据通信的基础知识&#xff0c;物理层下面的传输媒体 前言一、物理层的基本概念1. 什么是物理层2. 物理层的核心使命3. 物理层的四大特性 二、数据通信的基础知识1. 数据通信系统的基本模型1.1 …

Linux系统性能优化

目录 Linux系统性能优化 一、性能优化概述 二、性能监控工具 1. 基础工具 2. 高级工具 三、子系统优化策略 1. CPU优化 2. 内存优化 3. 磁盘I/O优化 4. 网络优化 四、资源限制优化 1. ulimit 2. cgroups&#xff08;控制组&#xff09; 五、安全与注意事项 六、…

【streamlit streamlit中 显示 mermaid 流程图有两种方式】

streamlit中显示mermaid 流程图有两种方式 mermaind示例 code """ flowchart LRmarkdown["This **is** _Markdown_"]newLines["Line1Line 2Line 3"]markdown --> newLinesmarkdown["This **is** _Markdown_"]newLines[&quo…

Rust调用 DeepSeek API

Rust 实现类似 DeepSeek 的搜索工具 使用 Rust 构建一个高效、高性能的搜索工具需要结合异步 I/O、索引结构和查询优化。以下是一个简化实现的框架: 核心组件设计 索引结构 use std::collections::{HashMap, HashSet}; use tantivy::schema::{Schema, TEXT, STORED}; use …

Unity3D仿星露谷物语开发69之动作声音

1、目标 Player动作时产生的声音&#xff0c;比如砍倒树木、砸石头。 2、修复NPC快速行进的bug&#xff08;与本节无关&#xff09; 修改NPCMovement.cs脚本的MoveToGridPositionRoutine方法。 确保npcCalculatedSpeed的速度不少于最慢速度。 原代码&#xff1a; 修改后的…

【Node.js 的底层实现机制】从事件驱动到异步 I/O

简介 Node.js 作为 JavaScript 后端运行环境&#xff0c;其核心优势在于高并发处理能力和非阻塞 I/O 模型。 特点&#xff1a; 高并发处理&#xff1a;单线程事件循环高效处理大量并发连接I/O 密集型任务&#xff1a;非阻塞 I/O 模型避免线程切换开销&#xff0c;不适合 CPU…

nginx服务器配置时遇到的一些问题

京东云 CentOS 8.2 64位 Nginx配置文件修改后需要重启或重载服务的原因以及不重启的后果&#xff1a; ​​工作进程不主动重读配置​​&#xff1a; Nginx采用master-worker多进程架构。master进程读取配置文件并管理worker进程&#xff0c;worker进程处理实际请求。修改配置…

【论文阅读 | CVPR 2024 |Fusion-Mamba :用于跨模态目标检测】

论文阅读 | CVPR 2024 |Fusion-Mamba &#xff1a;用于跨模态目标检测 1.摘要&&引言2.方法2.1 预备知识2.2 Fusion-Mamba2.2.1 架构特征提取与多模态融合&#xff08;FMB模块&#xff09;FMB的应用与输出2.2.2 关键组件3.2.2.1 SSCS 模块&#xff1a;浅层跨模态特征交互…

Nginx-Ingress-Controller自定义端口实现TCP/UDP转发

背景1 使用deployment部署一个http服务&#xff0c;配合使用ingresstls的解析在ingress终止。 apiVersion: networking.k8s.io/v1 kind: Ingress metadata:annotations:name: test.comnamespace: rcs-netswitch-prod spec:defaultBackend:service:name: rcs-netswitch-prodpo…

基于Vue.js的图书管理系统前端界面设计

一、系统前端界面设计要求与效果 &#xff08;一&#xff09;系统功能结构图 设计一个基于Vue.js的图书管理系统前端界面。要充分体现Vue的核心特性和应用场景&#xff0c;同时结合信息管理专业的知识。要求系统分为仪表盘、图书管理、借阅管理和用户管理四个主要模块&#x…