在 HarmonyOS 开发中,工具类的封装可以极大提升开发效率和代码可维护性。本文将详细讲解我封装的一套工具类,涵盖用户认证、沉浸式全屏、日志打印、网络请求、截图保存、状态栏控制、轻提示等常用功能,并提供完整的使用示例。
FullScreen
------沉浸式全屏设置
功能说明:
- 开启/关闭沉浸式全屏(穿透手机顶底栏)
- 获取状态栏和导航栏高度,用于页面布局适配
FullScreen
封装的工具类中需要获取上下文this:
- 在
EntryAbility
中onCreate
生命周期钩子函数中:
typescript
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
...
// 通过应用状态管理对上下文进行状态创建设置
AppStorage.setOrCreate('context', this.context)
}
- 在
FullScreen
工具类中进行获取使用
typescript
class FullScreen {
//开启沉浸式全屏
async enable() {
try {
// 获取当前窗口Context对象
const ctx = AppStorage.get<Context>(CONTEXT)
...
}
}
//关闭沉浸式全屏
async disable() {
try {
// 获取当前窗口Context对象
const ctx = AppStorage.get<Context>(CONTEXT)
...
}
}
}
工具类方法:
typescript
/**
* description: [沉侵式系统:穿透手机顶底栏]
* 1.通过内置window对象获取当前窗口对象
* 2.调用window对象setWindowLayoutFullScreen方法开启沉浸式全屏
* 3.通过window对象getWindowAvoidArea方法获取状态栏高度和导航条高度
* 4.将状态栏高度和导航条高度存储在AppStorage中
* */
import { CONTEXT, NAVIGATION_BAR_HEIGHT, STATUS_BAR_HEIGHT } from '../constants'
import { window } from '@kit.ArkUI';
import { logger } from './Logger';
class FullScreen {
//开启沉浸式全屏
async enable() {
try {
// 获取当前窗口Context对象
const ctx = AppStorage.get<Context>(CONTEXT)
if (ctx) {
// 获取窗口对象
const win = await window.getLastWindow(ctx);
// 开启全屏(沉浸式)
await win.setWindowLayoutFullScreen(true)
// 获取状态栏高度
const statusBarHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM)
// 存储状态栏高度
AppStorage.setOrCreate(STATUS_BAR_HEIGHT, px2vp(statusBarHeight.topRect.height))
logger.info('FullScreen StatusBarHeight', px2vp(statusBarHeight.topRect.height) + '')
// 获取导航条高度
const navigationBarHeight = win.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR)
// 存储导航条高度
AppStorage.setOrCreate(NAVIGATION_BAR_HEIGHT, px2vp(navigationBarHeight.bottomRect.height))
logger.info('FullScreen StatusBarHeight', px2vp(navigationBarHeight.bottomRect.height) + '')
}
} catch (err) {
logger.error('FullScreen Open Error', err)
}
}
//关闭沉浸式全屏
async disable() {
try {
// 获取当前窗口Context对象
const ctx = AppStorage.get<Context>(CONTEXT)
if (ctx) {
// 获取窗口对象
const win = await window.getLastWindow(ctx)
// 关闭全屏(沉浸式)
win.setWindowLayoutFullScreen(false)
// 恢复状态栏高度和导航条高度为0
AppStorage.setOrCreate(STATUS_BAR_HEIGHT, 0)
AppStorage.setOrCreate(NAVIGATION_BAR_HEIGHT, 0)
}
} catch (err) {
logger.error('FullScreen Close Error', err)
}
}
}
/**
* 【使用方法】
* 开启沉浸式全屏 fullScreen.enable()
* 1.可在UIAbility中生命周期onWindowStageCreate钩子函数中开启沉浸式全屏
* 2.通过`@StorageProp(...)`获取本地存储的状态栏高度和导航条高度
* 3.页面中以获取的本地存储值动态设置状态栏高度和导航条高度为上下padding进行避让
*
* 相关沉侵式系统API:
* expandSafeArea 控制组件扩展其安全区域
* setKeyboardAvoidMode 控制虚拟键盘抬起时页面的避让模式
* getKeyboardAvoidMode 返回虚拟键盘抬起时页面的避让模式
*
* 关闭沉浸式全屏 fullScreen.disable()
* */
export const fullScreen = new FullScreen()
StatusBar
------ 状态栏文字颜色控制
功能说明:
- 切换手机顶部状态栏文字颜色(深色/浅色)
工具类方法:
typescript
/**
* description: [顶部状态栏文字颜色切换 黑色/白色]
* */
import { CONTEXT } from "../constants"
import { window } from "@kit.ArkUI"
class StatusBar {
// 深色模式
setDarkBar() {
this.setBar({ statusBarContentColor: '#000000' })
}
// 浅色模式
ssetLightBar() {
this.setBar({ statusBarContentColor: '#ffffff' })
}
// 设置颜色API
async setBar(config: window.SystemBarProperties) {
//获取context对象
const ctx = AppStorage.get<Context>(CONTEXT)
//判断context对象是否存在 健壮性检测
if (ctx) {
//获取当前窗口对象
const win = await window.getLastWindow(ctx)
//调用API设置状态栏颜色
win.setWindowSystemBarProperties(config)
}
}
}
/**
* 【使用方法】
* statusBar.setDarkBar() //设置顶部状态栏【时间/电量..】文字深色模式为 黑色
* statusBar.setLightBar() //设置顶部状态栏【时间/电量..】文字浅色模式为 白色
* */
export const statusBar = new StatusBar()
Logger
------ 日志打印封装
功能说明:
- 引用鸿蒙三方库
@abner/log
二次封装配置,便于使用 - 支持多种日志级别(info/debug/warn/error/fatal)
- 自动识别 JSON 数据并格式化输出
二次封装:
typescript
/**
* description: [日志打印] 引用三方库 @abner/log 进行二次封装
* */
import { Log } from '@abner/log'
import { describe } from '@ohos/hypium'
Log.init({
tag: 'hm_interview', //打印的标签,默认为: hm_interview
domain: 0x0000, //输出日志所对应的业务领域,默认为0x0000
close: false, //关闭日志输出,默认true为关闭,false为开启
isHilog: true, //是否为鸿蒙日志系统
showLogLocation: true, //是否展示点击的位置,默认为true是展示 ,false为不展示
logSize: 800 //日志每次输出大小,最大1024字节
})
/**
* 【使用方法】
* logger.info("我是一个info类型日志", "testTag")
* logger.debug("我是一个debug类型日志", "testTag")
* logger.warn("我是一个warn类型日志", "testTag")
* logger.error("我是一个error类型日志", "testTag")
* logger.fatal("我是一个fatal类型日志", "testTag")
*
* 直接传递JSON对象 会自动转换成JSON字符串
* logger.info({ "name": "AbnerMing", "age": 18 })
*
* */
export { Log as logger }
SaveAlbum
------ 组件截图并保存至相册(截图分享)
✅ 使用说明
- 作用 :
.id('share')
为当前组件设置一个唯一的标识符,便于后续通过componentSnapshot.get('share')
获取该组件的视图快照。 - 应用场景:常用于分享弹窗、海报生成等需要对 UI 组件进行截图并保存的场景。
- 配合工具类 :与
SaveAlbum
工具类结合使用,实现截图 → 保存至沙箱 → 写入相册的完整流程。
工具类方法:
typescript
import { componentSnapshot } from '@kit.ArkUI'
import { image } from '@kit.ImageKit'
import { fileIo, fileUri } from '@kit.CoreFileKit'
import { photoAccessHelper } from '@kit.MediaLibraryKit'
import { CONTEXT } from '../constants'
class SaveAlbum {
// 组件截图
static async componentShot(compoentID: string) {
// 获取组件截图
const img = await componentSnapshot.get(compoentID)
// 创建imagePacker对象实例
const imagePacker = image.createImagePacker()
// 获取到图片arrayBuffer 返回 图片二进制流
return await imagePacker.packToData(img, { format: 'image/png', quality: 99 })
}
// 图片写入沙箱
static imgWriteToSandbox(imgArrayBuffer: ArrayBuffer) {
// 获取上下文
const ctx = AppStorage.get<Context>(CONTEXT)
// 创建图片路径
const imgPath = ctx?.cacheDir + '/' + Date.now() + '.png'
// 创建文件
const file = fileIo.openSync(imgPath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE)
// 写入文件
fileIo.writeSync(file.fd, imgArrayBuffer)
// 关闭文件
fileIo.closeSync(file.fd)
return imgPath
}
// 将沙箱图片写入相册
static async sandboxImgToAlbum(imgPath: string) {
// 获取上下文
const ctx = AppStorage.get<Context>(CONTEXT)
// 获取图片uri
const uri = fileUri.getUriFromPath(imgPath)
// 创建相册资源请求
const photoRequest = photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(ctx, uri)
// 获取相册访问实例
const photoHelper = photoAccessHelper.getPhotoAccessHelper(ctx)
// 写入相册
await photoHelper.applyChanges(photoRequest)
}
}
export { SaveAlbum }
📌 示例调用方式
typescript
// 截图组件
const imgArrayBuffer = await SaveAlbum.componentShot('share')
// 图片写入沙箱
const imgPath = SaveAlbum.imgWriteToSandbox(imgArrayBuffer)
// 将沙箱图片写入相册
await SaveAlbum.sandboxImgToAlbum(imgPath)
ShowToast
- 轻提示封装
功能说明:
- 引用鸿蒙三方库
@jxt/xt_hud
二次封装配置,便于使用 - 引用鸿蒙原生
promptAction
二次封装,提供统一调用接口 - 对于简单的提示场景,直接使用
showToastmsg
即可 - 对于复杂交互或需要 Loading、Progress的场景,可以结合三方库调用
ShowToast
封装的工具类中需要获取上下文this:
- 在
EntryAbility
中onCreate
生命周期钩子函数中:
typescript
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
...
// 通过应用状态管理对上下文进行状态创建设置
AppStorage.setOrCreate('context', this.context)
}
- 在
XTPromptInit
工具方法获取窗口对象中进行获取使用
typescript
async XTPromptInit() {
try {
const ctx = AppStorage.get<Context>(CONTEXT)
if (ctx) {
// 获取窗口对象
const win = await window.getLastWindow(ctx);
...
}
}
}
}
⚠️ 三方库
@jxt/xt_hud
需要先在 windowStage.loadContent 中进行初始化配置
typescript
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
return;
}
// XTPromptHUD 全局初始化
showToast.XTPromptInit()
});
工具类方法:
typescript
import promptAction from '@ohos.promptAction';
import { IShowToast, EToastTypeColor, IShowDialog } from '../../commons/types'
import { CONTEXT } from '../constants';
import { window } from '@kit.ArkUI';
import { logger } from '.'
import {
XTPromptHUD,
XTHUDToastOptions,
XTHUDLoadingOptions,
XTHUDProgressOptions,
XTHUDReactiveBaseOptions
} from '@jxt/xt_hud'
/**
* ShowToast 类
* 功能:封装统一的提示工具,包括轻提示(Toast)、弹窗确认(Dialog)和第三方 HUD 的初始化配置。
*/
class ShowToast {
/**
* 显示轻提示 Toast
* 默认类型为 Info,时长为 2000 毫秒。
*
* @param opt - 提示参数对象,包含 message、type 和 duration
*/
showToastmsg(opt: IShowToast) {
promptAction.showToast({
message: opt.message,
textColor: opt.type || EToastTypeColor.Info, // 文字颜色,默认 Info 类型颜色
duration: opt.duration || 2000, // 显示时长,默认 2 秒
})
}
/**
* 显示确认对话框 Dialog
* 支持自定义标题、内容和按钮。默认按钮为"取消"和"确定"。
*
* @param opt - 弹窗参数对象,包含 title、message 和 buttons
* @returns Promise<number> 点击按钮的索引(0 取消,1 确定)
*/
showDialog(opt: IShowDialog) {
return promptAction.showDialog({
title: opt.title || '提示', // 标题,默认 "提示"
message: opt.message || '确定?', // 内容,默认 "确定?"
buttons: [
{
text: (opt.buttons && opt.buttons[0].text) || '取消',
color: $r('app.color.common_gray_03'), // 取消按钮颜色
},
{
text: (opt.buttons && opt.buttons[0].text) || '确定',
color: $r('app.color.common_main_color'),// 确定按钮颜色
},
],
})
}
/**
* 初始化第三方 HUD 组件(XTPromptHUD)
* 配置全局样式和行为,如模态显示、队列模式等。
* 使用前需确保已正确引入 [@jxt/xt_hud]库。
*/
async XTPromptInit() {
try {
const ctx = AppStorage.get<Context>(CONTEXT) // 获取上下文
if (ctx) {
// 获取窗口对象
const win = await window.getLastWindow(ctx);
// Toast 全局配置:启用队列模式
XTPromptHUD.globalConfigToast(win.getUIContext(),
(options: XTHUDToastOptions) => {
options.isQueueMode = true
})
// Loading 全局配置:模态显示,遮罩层透明度为 50%,字体大小为 12
XTPromptHUD.globalConfigLoading(win.getUIContext(),
(options: XTHUDLoadingOptions) => {
options.isModal = true
options.maskColor = 'rgba(0,0,0,0.5)'
options.fontSize = 12
})
// Progress 全局配置:模态显示
XTPromptHUD.globalConfigProgress(win.getUIContext(),
(options: XTHUDProgressOptions) => {
options.isModal = true
})
// ReactiveBase 全局配置(用于进度条等):模态显示
XTPromptHUD.globalConfigProgress(win.getUIContext(),
(options: XTHUDReactiveBaseOptions) => {
options.isModal = true
})
}
} catch (err) {
logger.error('ShowToast XTPromptInit Error', err)
}
}
}
// 导出单例实例
export const showToast = new ShowToast();
使用方法
typescript
// 显示轻提示 Toast
showToast.showToastmsg({ message: '这是一条提示', type: EToastTypeColor.Info });
// 显示确认对话框 Dialog
showToast.showDialog({ title: '退出登录', message: '是否确认退出?',
buttons: [
{ text: '取消', color: '#999' },
{ text: '确定', color: '#FF0000' }
]
})
const res = await showToast.showDialog({ title: '提示',message: '确定执行此操作?'})
if (res.index === 1) {
// 用户点击了"确定"
}
// XTPromptHUD
import { XTPromptHUD } from '@jxt/xt_hud'
// Toast 轻提示
XTPromptHUD.showToast('success')
//Loading 加载状态
XTPromptHUD.showLoading('加载中...') //开启Loading
XTPromptHUD.hideLoading() //关闭Loading
//Progress 加载进度条
this.progress = 0
this.interval = setInterval(() => {
this.progress++
XTPromptHUD.showProgress(this.progress)
if (this.progress >= 100) {
clearInterval(this.interval)
this.interval = null
}
}, 100)
Request
- 网络请求封装(基于 Axios)
功能说明:
instance
创建 axios 实例并设置基础 URL 和超时时间request interceptor
自动在请求头中携带 Tokenresponse interceptor
统一处理响应数据、Token 失效跳转、提示等Request class
封装请求方法,支持泛型调用http 实例
导出可复用的请求工具实例
使用方法:
typescript
import axios, {
AxiosRequestConfig,
AxiosResponse,
AxiosError,
InternalAxiosRequestConfig
} from '@ohos/axios'
import {
BASE_URL, // 请求基础地址
TIME_OUT, // 请求超时时间
SUCCESS_CODE, // 成功状态码
TOKEN_INVALID_CODE // Token 失效状态码
} from '../constants'
import {
authUser, // 用户认证工具类
logger, // 日志记录工具
showToast // 提示工具类
} from '../utils'
import { router } from '@kit.ArkUI'; // HarmonyOS 路由模块
import { EToastTypeColor } from '../types'; // Toast 颜色类型枚举
/**
* 创建一个 axios 实例,并配置基础请求参数。
*
* baseURL: 所有请求的基础路径
* timeout: 请求超时时间(毫秒)
*/
const instance = axios.create({
baseURL: BASE_URL,
timeout: TIME_OUT,
})
/**
* 请求拦截器
* 在请求发送前对配置进行处理,例如添加 token 到请求头
*
* @param config - 当前请求的配置对象
* @returns 修改后的请求配置对象
*/
instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// 获取用户 token 并添加到 Authorization 请求头
const token = authUser.getToken()
config.headers['Authorization'] = token ? 'Bearer ' + token : ''
return config;
},
(error: AxiosError) => {
// 请求出错时的日志记录
logger.info(error)
return Promise.reject(error);
}
)
/**
* 响应拦截器
* 对响应数据进行统一处理,如判断是否登录过期、跳转登录页等
*
* @param response - 响应数据
* @returns 响应中的业务数据或抛出错误
*/
instance.interceptors.response.use(
(response: AxiosResponse) => {
// 如果返回的状态码为成功码,返回 data 字段数据
if (response.data.code === SUCCESS_CODE) {
return response.data.data
}
// 否则以 reject 的方式返回错误信息,便于 catch 捕获
return Promise.reject(response.data)
},
(error: AxiosError) => {
// 如果是 Token 失效,则清除用户信息并跳转登录页
if (error.response?.status === TOKEN_INVALID_CODE) {
authUser.clearUser()
router.pushUrl({ url: 'pages/LoginPage' }, router.RouterMode.Single)
showToast.showToastmsg({
message: '登录已过期,请重新登录',
type: EToastTypeColor.Warning
})
}
// 返回错误信息
return Promise.reject(error.message)
}
)
/**
* Request 类
* 封装基于 axios 实例的通用请求方法
*/
class Request {
/**
* 发起网络请求
*
* @param config - 请求配置对象
* @returns 返回泛型 R 类型的数据
*/
request<R, Q>(config: AxiosRequestConfig<Q>) {
return instance<R, R, Q>(config)
}
}
/**
* 导出封装好的 http 实例
* 使用方式:http.request<ResponseData,RequestData>({method: 'GET',url: '/api/user'})
*/
export const http = new Request()
AuthUser
- 用户鉴权
功能说明:
init()
初始化本地持久化存储(用户信息和 Token)getUserInfo()
获取当前用户信息setUserInfo()
设置用户信息并更新 Token,触发事件通知setToken()
单独设置 TokengetToken()
获取 TokenclearUser()
清除用户信息和 Token,触发事件通知authRoutePermission()
控制页面跳转权限,无 Token 则跳转登录页
🧠 使用建议:
- 初始化调用 :在应用启动时调用
authUser.init()
。 - 用户登录后 :使用
authUser.setUserInfo(userInfo)
设置用户信息。 - 用户登出时 :调用
authUser.clearUser()
清除信息。 - 页面跳转鉴权 :使用
authUser.authRoutePermission({ url: 'pages/Profile' })
控制访问权限。
typescript
import {
USER_INFO, // 用户信息存储 key
TOKEN_KEY, // Token 存储 key
EMIT_EVENT // 用户状态变更事件名
} from '../../commons/constants'
import { IUserData } from '../../models/types' // 用户数据类型定义
import { router } from '@kit.ArkUI' // HarmonyOS 路由模块
import emitter from '@ohos.events.emitter' // 事件发射器,用于全局通信
/**
* AuthUser 类
* 功能:用户认证与权限管理工具类
*
* 包括:
* - 初始化本地持久化存储
* - 获取/设置用户信息和 Token
* - 清除用户信息
* - 页面跳转鉴权控制
*/
class AuthUser {
/**
* 初始化本地持久化存储
* 将用户信息和 Token 持久化到 AppStorage 中
*/
init() {
PersistentStorage.persistProps([{
key: USER_INFO,
defaultValue: {} as IUserData
}])
PersistentStorage.persistProps([{
key: TOKEN_KEY,
defaultValue: '' as string
}])
}
/**
* 获取当前用户信息
* @returns 用户信息对象或空对象
*/
getUserInfo(): IUserData | object {
return AppStorage.get(USER_INFO) || {}
}
/**
* 设置用户信息并同步保存 Token
* @param userInfo 用户数据对象
*/
setUserInfo(userInfo: IUserData) {
AppStorage.set(USER_INFO, userInfo)
this.setToken(userInfo.token)
// 触发用户信息变更事件
emitter.emit(EMIT_EVENT)
}
/**
* 设置 Token 到 AppStorage
* @param token 用户 Token 字符串
*/
setToken(token: string) {
AppStorage.set(TOKEN_KEY, token)
}
/**
* 获取当前用户的 Token
* @returns Token 字符串 或 空字符串
*/
getToken(): string {
return AppStorage.get(TOKEN_KEY) || ''
}
/**
* 清除用户信息和 Token,并触发事件
*/
clearUser() {
AppStorage.set(USER_INFO, {} as IUserData)
AppStorage.set(TOKEN_KEY, '')
// 触发用户信息变更事件
emitter.emit(EMIT_EVENT)
}
/**
* 路由跳转鉴权控制
* 如果未登录,则跳转至登录页
*
* @param opt - 跳转参数或回调函数
*/
authRoutePermission(opt: router.RouterOptions | Function) {
const isHasToken = this.getToken()
if (typeof opt === 'function') {
// 如果是函数,则根据是否有 Token 决定是否执行
isHasToken ? opt() : router.pushUrl({ url: 'pages/LoginPage' })
} else {
// 如果是路由配置对象,则包装参数后跳转
const jumpToLogin = () => {
const target_url = opt.url
opt.params = { url: target_url, params: opt.params }
router.pushUrl({ url: 'pages/LoginPage', params: opt })
}
isHasToken ? router.pushUrl(opt) : jumpToLogin()
}
}
}
// 导出单例实例
export const authUser = new AuthUser()
🎯 总结
本篇文章详细介绍了我在 HarmonyOS 开发中常用的工具类及其使用方式,涵盖了从用户认证、网络请求、UI 控制到日志打印等多个方面,适合刚入门的小白直接复制粘贴使用。合理利用这些工具类,可以大幅提升开发效率和代码质量。
如需进一步扩展,也可以基于这些基础工具类添加更多业务逻辑封装。希望对你有所帮助!🚀