在 HarmonyOS 应用开发中,网络请求与数据持久化是每个应用必不可少的基础功能。HarmonyOS 提供了完善的原生解决方案——从轻量级的 Preferences 键值存储到关系型数据库,再到分布式 KV-Store,能够满足绝大多数场景需求。本文将从实际代码出发,梳理常用操作,便于开发者在项目中直接参考使用。
HarmonyOS 网络请求与数据持久化完整指南
HTTP 网络请求
@ohos.net.http 基础请求
import http from '@ohos.net.http'
// 发起 GET 请求
async function fetchData(url: string): Promise {
const httpRequest = http.createHttp()
try {
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
header: {
'Content-Type': 'application/json'
},
connectTimeout: 60000,
readTimeout: 60000,
extraData: {} // GET 请求通常不需要携带请求体
})
if (response.responseCode === 200) {
const result = JSON.parse(response.result as string) as ResponseData
return result
} else {
throw new Error(`HTTP 错误: ${response.responseCode}`)
}
} finally {
httpRequest.destroy() // 必须销毁请求对象,释放资源
}
}
// 发起 POST 请求
async function postData(url: string, body: Object): Promise {
const httpRequest = http.createHttp()
try {
const response = await httpRequest.request(url, {
method: http.RequestMethod.POST,
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`
},
extraData: JSON.stringify(body)
})
return JSON.parse(response.result as string) as ResponseData
} finally {
httpRequest.destroy()
}
}
// PUT 和 DELETE 请求用法类似,只需更改 method 参数
请求事件监听
const httpRequest = http.createHttp()
httpRequest.on('headerReceive', (err, header) => {
console.info('已收到响应头')
})
httpRequest.on('dataReceive', (data) => {
console.info('收到数据片段')
})
httpRequest.on('dataEnd', () => {
console.info('数据接收完毕')
})
httpRequest.on('responseReceive', (response) => {
console.info('收到完整响应')
})
// 流式接收,适用于大文件下载
httpRequest.requestInStream(url, options)
// 取消正在进行的请求
httpRequest.destroy()
封装网络请求工具类
import http from '@ohos.net.http'
const BASE_URL = 'https://api.example.com'
interface ApiResponse {
code: number
message: string
data: T
}
class HttpClient {
private static instance: HttpClient
private token: string = ''
static getInstance(): HttpClient {
if (!HttpClient.instance) {
HttpClient.instance = new HttpClient()
}
return HttpClient.instance
}
setToken(token: string) {
this.token = token
}
private getHeaders(): Record {
const headers: Record = {
'Content-Type': 'application/json'
}
if (this.token) {
headers['Authorization'] = `Bearer ${this.token}`
}
return headers
}
async get(path: string, params?: Record): Promise> {
let url = `${BASE_URL}${path}`
if (params) {
const query = Object.entries(params)
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join('&')
url += `?${query}`
}
return this.request(url, http.RequestMethod.GET)
}
async post(path: string, body?: Object): Promise> {
const url = `${BASE_URL}${path}`
return this.request(url, http.RequestMethod.POST, body)
}
async put(path: string, body?: Object): Promise> {
const url = `${BASE_URL}${path}`
return this.request(url, http.RequestMethod.PUT, body)
}
async delete(path: string): Promise> {
const url = `${BASE_URL}${path}`
return this.request(url, http.RequestMethod.DELETE)
}
private async request(
url: string,
method: http.RequestMethod,
body?: Object
): Promise> {
const httpRequest = http.createHttp()
try {
const response = await httpRequest.request(url, {
method,
header: this.getHeaders(),
connectTimeout: 30000,
readTimeout: 30000,
extraData: body ? JSON.stringify(body) : undefined
})
if (response.responseCode === 200) {
return JSON.parse(response.result as string) as ApiResponse
}
if (response.responseCode === 401) {
// Token 过期,执行重新认证
this.handleAuthError()
throw new Error('认证已过期')
}
throw new Error(`请求失败: ${response.responseCode}`)
} catch (error) {
console.error(`HTTP 请求出错: ${error}`)
throw error
} finally {
httpRequest.destroy()
}
}
private handleAuthError() {
this.token = ''
// 可在此跳转登录页或自动刷新 Token
}
}
export default HttpClient.getInstance()
数据持久化
Preferences 轻量存储(键值对)
import preferences from '@ohos.data.preferences'
const PREFERENCES_NAME = 'my_app_prefs'
async function getPreferences(context: Context): Promise {
return preferences.getPreferences(context, PREFERENCES_NAME)
}
// 写入数据
async function sa veSetting(context: Context, key: string, value: preferences.ValueType) {
const prefs = await getPreferences(context)
await prefs.put(key, value)
await prefs.flush() // 持久化到磁盘
}
// 读取数据
async function getSetting(context: Context, key: string): Promise {
const prefs = await getPreferences(context)
return prefs.get(key, '') // 设置默认值为空字符串
}
// 删除指定键
async function removeSetting(context: Context, key: string) {
const prefs = await getPreferences(context)
await prefs.delete(key)
await prefs.flush()
}
// 清空所有存储
async function clearSettings(context: Context) {
const prefs = await getPreferences(context)
await prefs.clear()
await prefs.flush()
}
// 常见使用场景示例
// sa veSetting(context, 'user_token', 'xxx')
// sa veSetting(context, 'is_first_launch', true)
// sa veSetting(context, 'last_login_time', 1700000000)
RelationalDB 关系型数据库(SQLite)
import relationalStore from '@ohos.data.relationalStore'
const STORE_CONFIG: relationalStore.StoreConfig = {
name: 'app_database.db',
securityLevel: relationalStore.SecurityLevel.S1
}
// 创建数据表
const CREATE_TABLE_SQL = `
CREATE TABLE IF NOT EXISTS user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER,
created_at INTEGER
)`
async function initDB(context: Context): Promise {
const store = await relationalStore.getRdbStore(context, STORE_CONFIG)
await store.executeSql(CREATE_TABLE_SQL)
return store
}
// 插入用户数据
async function insertUser(store: relationalStore.RdbStore, user: User): Promise {
const valueBucket: relationalStore.ValuesBucket = {
'name': user.name,
'age': user.age,
'created_at': Date.now()
}
return store.insert('user', valueBucket)
}
// 查询用户列表,可按年龄筛选
async function queryUsers(store: relationalStore.RdbStore, ageFilter?: number): Promise {
const predicates = new relationalStore.RdbPredicates('user')
if (ageFilter) {
predicates.equalTo('age', ageFilter)
}
predicates.orderByDesc('created_at')
const resultSet = await store.query(predicates)
const users: User[] = []
while (resultSet.goToNextRow()) {
users.push({
id: resultSet.getLong(resultSet.getColumnIndex('id')),
name: resultSet.getString(resultSet.getColumnIndex('name')),
age: resultSet.getLong(resultSet.getColumnIndex('age')),
created_at: resultSet.getLong(resultSet.getColumnIndex('created_at'))
})
}
resultSet.close()
return users
}
// 更新用户名称
async function updateUser(store: relationalStore.RdbStore, id: number, name: string): Promise {
const valueBucket: relationalStore.ValuesBucket = { 'name': name }
const predicates = new relationalStore.RdbPredicates('user')
predicates.equalTo('id', id)
return store.update(valueBucket, predicates)
}
// 删除指定用户
async function deleteUser(store: relationalStore.RdbStore, id: number): Promise {
const predicates = new relationalStore.RdbPredicates('user')
predicates.equalTo('id', id)
return store.delete(predicates)
}
KV-Store 分布式键值数据库
import distributedKVStore from '@ohos.data.distributedKVStore'
// 创建 KV-Store 分布式数据库
const options: distributedKVStore.Options = {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: true, // 自动同步到其他设备
kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION
}
async function createKVStore(context: Context): Promise {
return distributedKVStore.createKVStore(context, 'distributed_store', options)
}
// 写入键值对
kvStore.put('sync_key', 'sync_value')
// 读取键值对
const value = await kvStore.get('sync_key')
// 手动同步数据到其他设备
kvStore.sync(['device_id_1', 'device_id_2'], distributedKVStore.SyncMode.PUSH_ONLY)
文件存储
应用文件目录
import fileIo from '@ohos.file.fs'
// 应用私有目录路径
const filesDir = context.filesDir // /data/app/el2/100/.../files
const cacheDir = context.cacheDir // /data/app/el2/100/.../cache
const tempDir = context.tempDir // /data/app/el2/100/.../temp
const preferencesDir = context.preferencesDir
// 写入文件
const file = fileIo.openSync(`${filesDir}/data.json`, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY)
fileIo.writeSync(file.fd, JSON.stringify(data))
fileIo.closeSync(file)
// 读取文件
const readFile = fileIo.openSync(`${filesDir}/data.json`, fileIo.OpenMode.READ_ONLY)
const content = fileIo.readSync(readFile.fd)
fileIo.closeSync(readFile)
// 判断文件是否存在
const exists = fileIo.accessSync(`${filesDir}/data.json`)
