跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
TypeScript大前端

鸿蒙 APP 开发实战:网络请求与数据持久化

鸿蒙 APP 开发中的网络请求与数据持久化技术。内容包括鸿蒙官方 HTTP 请求库的配置与封装,实现了 GET/POST 请求、拦截器及错误处理机制。通过商品服务和用户服务的代码示例,展示了如何调用 API 并处理响应数据。此外,文章还涵盖了网络状态检测的实现,以及利用 Preferences 进行轻量级键值对存储和利用 SQLite 进行结构化数据持久化的具体实践。最后提供了加载动画与错误界面的组件实现,帮助开发者提升应用的用户体验。

无尘发布于 2026/2/27更新于 2026/10/24100 浏览
鸿蒙 APP 开发实战:网络请求与数据持久化

鸿蒙 APP 开发:网络请求与数据持久化

图片

核心内容

本文介绍鸿蒙应用开发中的网络通信与本地数据存储技术,涵盖官方 HTTP 请求库的使用、Preferences 轻量级存储及 SQLite 关系型数据库的集成方案。

主要内容:

  • 掌握鸿蒙官方 HTTP 请求库的配置与使用;
  • 实现商品列表与用户信息的网络请求交互;
  • 理解数据持久化原理,使用 Preferences 与 SQLite 存储本地数据;
  • 优化网络请求体验,包括加载动画、错误处理及网络状态检测。

一、网络请求基础

1.1 鸿蒙 HTTP 请求库

HarmonyOS Next 提供官方 HTTP 请求库,支持 HTTP/HTTPS 协议,功能包括发送 GET/POST/PUT/DELETE 请求、设置请求头与参数、文件上传下载、拦截器配置以及超时重试机制。

1.2 实战:HTTP 请求库配置
1. 配置网络权限

在 entry/src/main/module.json5 中添加网络权限:

{
  "module": {
    "requestPermissions": [
      {"name": "ohos.permission.INTERNET"},
      {"name": "ohos.permission.READ_NETWORK_STATE"},
      {"name": "ohos.permission.WRITE_NETWORK_STATE"}
    ]
  }
}
2. 网络请求工具类

创建 entry/src/main/ets/utils/HttpUtils.ets:

import http from '@ohos.net.http';

// 网络请求配置
const HTTP_CONFIG = {
  baseUrl: 'https://api.example.com', // 替换为你的 API 地址
  timeout: 10000, // 超时时间(毫秒)
  retryCount: 3 // 重试次数
};

// 网络请求工具类
export class HttpUtils {
  private static instance: HttpUtils | null = null;
  private httpRequest: http.HttpRequest | null = null;

  // 单例模式
  static getInstance(): HttpUtils {
    if (!HttpUtils.instance) {
      HttpUtils.instance = new HttpUtils();
    }
    return HttpUtils.instance;
  }

  // 初始化 HTTP 请求
  private initRequest(): void {
    if (!this.httpRequest) {
      this.httpRequest = http.createHttp();
    }
  }

  // 发送 GET 请求
  async get<T>(url: string, params?: Record<string, any>): Promise<T> {
    this.initRequest();
    const fullUrl = this.buildUrl(url, params);
    const response = await this.httpRequest!.request(fullUrl, {
      method: http.RequestMethod.GET,
      header: { 'Content-Type': 'application/json' },
      connectTimeout: HTTP_CONFIG.timeout,
      readTimeout: HTTP_CONFIG.timeout
    });
    return this.handleResponse<T>(response);
  }

  // 发送 POST 请求
  async post<T>(url: string, data?: Record<string, any>): Promise<T> {
    this.initRequest();
    const fullUrl = this.buildUrl(url);
    const response = await this.httpRequest!.request(fullUrl, {
      method: http.RequestMethod.POST,
      header: { 'Content-Type': 'application/json' },
      extraData: data,
      connectTimeout: HTTP_CONFIG.timeout,
      readTimeout: HTTP_CONFIG.timeout
    });
    return this.handleResponse<T>(response);
  }

  // 构建完整 URL
  private buildUrl(url: string, params?: Record<string, any>): string {
    let fullUrl = `${HTTP_CONFIG.baseUrl}${url}`;
    if (params) {
      const queryString = Object.keys(params).map(key => `${key}=${encodeURIComponent(params[key])}`).join('&');
      fullUrl += `?${queryString}`;
    }
    return fullUrl;
  }

  // 处理响应
  private async handleResponse<T>(response: http.HttpResponse): Promise<T> {
    if (response.responseCode === 200) {
      const result = JSON.parse(response.result.toString());
      if (result.code === 200) {
        return result.data;
      } else {
        throw new Error(result.message || '请求失败');
      }
    } else {
      throw new Error(`HTTP 错误:${response.responseCode}`);
    }
  }
}

二、网络请求实战

2.1 业务服务实现
1. 商品服务

创建 entry/src/main/ets/services/ProductService.ets:

import { HttpUtils } from '../utils/HttpUtils';
import { GoodsModel } from '../models/HomeModel';

// 商品 API 响应数据模型
export interface ProductResponseModel {
  code: number;
  message: string;
  data: Array<GoodsModel>;
}

// 商品服务
export class ProductService {
  private static instance: ProductService | null = null;

  static getInstance(): ProductService {
    if (!ProductService.instance) {
      ProductService.instance = new ProductService();
    }
    return ProductService.instance;
  }

  // 获取商品列表
  async getProductList(): Promise<Array<GoodsModel>> {
    const response = await HttpUtils.getInstance().get<Array<GoodsModel>>('/api/products');
    return response;
  }

  // 获取商品详情
  async getProductDetail(id: number): Promise<GoodsModel> {
    const response = await HttpUtils.getInstance().get<GoodsModel>(`/api/products/${id}`);
    return response;
  }
}
2. 用户服务

创建 entry/src/main/ets/services/UserService.ets:

import { HttpUtils } from '../utils/HttpUtils';

// 用户登录请求数据模型
export interface LoginRequestModel {
  username: string;
  password: string;
}

// 用户登录响应数据模型
export interface LoginResponseModel {
  code: number;
  message: string;
  data: { token: string; userInfo: UserInfoModel; };
}

// 用户信息数据模型
export interface UserInfoModel {
  id: number;
  username: string;
  avatar: string;
  nickname: string;
  email: string;
  phone: string;
  gender: number;
  birthday: string;
}

// 用户服务
export class UserService {
  private static instance: UserService | null = null;

  static getInstance(): UserService {
    if (!UserService.instance) {
      UserService.instance = new UserService();
    }
    return UserService.instance;
  }

  // 用户登录
  async login(request: LoginRequestModel): Promise<LoginResponseModel['data']> {
    const response = await HttpUtils.getInstance().post<LoginResponseModel['data']>('/api/login', request);
    return response;
  }

  // 用户注册
  async register(request: LoginRequestModel): Promise<LoginResponseModel['data']> {
    const response = await HttpUtils.getInstance().post<LoginResponseModel['data']>('/api/register', request);
    return response;
  }

  // 获取用户信息
  async getUserInfo(): Promise<UserInfoModel> {
    const response = await HttpUtils.getInstance().get<UserInfoModel>('/api/user/info');
    return response;
  }
}
2.2 网络状态检测
1. 网络状态服务

创建 entry/src/main/ets/services/NetworkService.ets:

import network from '@ohos.net.network';

// 网络状态类型
export type NetworkType = 'wifi' | 'cellular' | 'none';

// 网络状态服务
export class NetworkService {
  private static instance: NetworkService | null = null;

  static getInstance(): NetworkService {
    if (!NetworkService.instance) {
      NetworkService.instance = new NetworkService();
    }
    return NetworkService.instance;
  }

  // 获取当前网络状态
  getCurrentNetworkType(): NetworkType {
    const networkType = network.getNetworkTypeSync();
    switch (networkType) {
      case network.NetworkType.WIFI:
        return 'wifi';
      case network.NetworkType.CELLULAR:
        return 'cellular';
      default:
        return 'none';
    }
  }

  // 监听网络状态变化
  onNetworkTypeChange(callback: (type: NetworkType) => void): void {
    network.on('netAvailable', () => {
      callback(this.getCurrentNetworkType());
    });
    network.on('netUnavailable', () => {
      callback('none');
    });
  }
}
2. 网络状态组件

创建 entry/src/main/ets/components/NetworkStatusComponent.ets:

import { NetworkService } from '../services/NetworkService';

@Component
export struct NetworkStatusComponent {
  @State networkType: NetworkService.NetworkType = 'wifi';

  build() {
    Row({ space: 8 }) {
      Image(this.networkType === 'wifi' ? $r('app.media.wifi') : this.networkType === 'cellular' ? $r('app.media.cellular') : $r('app.media.none'))
        .width(20)
        .height(20)
        .objectFit(ImageFit.Contain);
      Text(this.networkType === 'wifi' ? 'WiFi' : this.networkType === 'cellular' ? '移动网络' : '无网络')
        .fontSize(14)
        .textColor(this.networkType === 'none' ? '#FF0000' : '#666666');
    }
    .width('auto')
    .height('auto')
    .padding(8, 16, 8, 16)
    .backgroundColor(this.networkType === 'none' ? '#FFE0E0' : '#F5F5F5')
    .borderRadius(20)
    .visible(this.networkType === 'none');
  }

  aboutToAppear() {
    this.networkType = NetworkService.getInstance().getCurrentNetworkType();
    NetworkService.getInstance().onNetworkTypeChange((type: NetworkService.NetworkType) => {
      this.networkType = type;
    });
  }
}

三、数据持久化实战

3.1 数据持久化分类

HarmonyOS Next 提供三种主要数据持久化方式:

方式功能适用场景
Preferences轻量级存储,支持键值对存储用户设置、应用配置、购物车数据等小体积数据
SQLite关系型数据库,支持复杂查询商品列表、用户信息、订单数据等结构化数据
Distributed Data分布式存储,支持跨设备数据同步超级终端多设备协同场景
3.2 实战:Preferences 存储
1. Preferences 工具类

创建 entry/src/main/ets/utils/PreferencesUtils.ets:

import preferences from '@ohos.data.preferences';
import { UIAbilityContext } from '@ohos.abilityAccessCtrl';

// Preferences 工具类
export class PreferencesUtils {
  private static instance: PreferencesUtils | null = null;
  private dataPreferences: preferences.Preferences | null = null;

  static getInstance(): PreferencesUtils {
    if (!PreferencesUtils.instance) {
      PreferencesUtils.instance = new PreferencesUtils();
    }
    return PreferencesUtils.instance;
  }

  // 初始化 Preferences
  async init(context: UIAbilityContext): Promise<void> {
    if (!this.dataPreferences) {
      this.dataPreferences = await preferences.getPreferences(context, 'app_preferences');
    }
  }

  // 获取值
  get<T>(key: string, defaultValue: T): T {
    if (!this.dataPreferences) {
      return defaultValue;
    }
    return this.dataPreferences.getSync(key, defaultValue) as T;
  }

  // 设置值
  async put<T>(key: string, value: T): Promise<void> {
    if (!this.dataPreferences) {
      return;
    }
    await this.dataPreferences.put(key, value);
    await this.dataPreferences.flush();
  }

  // 删除值
  async delete(key: string): Promise<void> {
    if (!this.dataPreferences) {
      return;
    }
    await this.dataPreferences.delete(key);
    await this.dataPreferences.flush();
  }

  // 清空所有值
  async clear(): Promise<void> {
    if (!this.dataPreferences) {
      return;
    }
    const keys = this.dataPreferences.keys();
    for (const key of keys) {
      await this.dataPreferences.delete(key);
    }
    await this.dataPreferences.flush();
  }
}
2. Preferences 应用

修改 entry/src/main/ets/services/UserService.ets:

import { HttpUtils } from '../utils/HttpUtils';
import { PreferencesUtils } from '../utils/PreferencesUtils';

// 用户服务
export class UserService {
  // ... 其他方法

  // 用户登录(添加 token 存储)
  async login(request: LoginRequestModel): Promise<LoginResponseModel['data']> {
    const response = await HttpUtils.getInstance().post<LoginResponseModel['data']>('/api/login', request);
    // 存储 token 到 Preferences
    await PreferencesUtils.getInstance().put('token', response.token);
    return response;
  }

  // 获取用户信息(添加 token 认证)
  async getUserInfo(): Promise<UserInfoModel> {
    const token = PreferencesUtils.getInstance().get<string>('token', '');
    HttpUtils.getInstance().addHeader('Authorization', `Bearer ${token}`);
    const response = await HttpUtils.getInstance().get<UserInfoModel>('/api/user/info');
    return response;
  }
}
3.3 实战:SQLite 存储
1. SQLite 数据库管理类

创建 entry/src/main/ets/utils/SQLiteUtils.ets:

import relationalStore from '@ohos.data.relationalStore';
import { UIAbilityContext } from '@ohos.abilityAccessCtrl';

// 数据库配置
const DB_CONFIG = {
  name: 'app_db.db',
  securityLevel: relationalStore.SecurityLevel.S1
};

// SQLite 数据库管理类
export class SQLiteUtils {
  private static instance: SQLiteUtils | null = null;
  private rdbStore: relationalStore.RdbStore | null = null;

  static getInstance(): SQLiteUtils {
    if (!SQLiteUtils.instance) {
      SQLiteUtils.instance = new SQLiteUtils();
    }
    return SQLiteUtils.instance;
  }

  // 初始化数据库
  async init(context: UIAbilityContext): Promise<void> {
    if (!this.rdbStore) {
      this.rdbStore = await relationalStore.getRdbStore(context, DB_CONFIG);
      // 创建用户表
      await this.createUserTable();
      // 创建商品表
      await this.createProductTable();
      // 创建购物车表
      await this.createCartTable();
    }
  }

  // 创建用户表
  private async createUserTable(): Promise<void> {
    const sql = ` CREATE TABLE IF NOT EXISTS user (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT NOT NULL,
      avatar TEXT,
      nickname TEXT,
      email TEXT,
      phone TEXT,
      gender INTEGER,
      birthday TEXT
    ) `;
    await this.rdbStore!.executeSql(sql);
  }

  // 创建商品表
  private async createProductTable(): Promise<void> {
    const sql = ` CREATE TABLE IF NOT EXISTS product (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      imageUrl TEXT,
      price REAL,
      originalPrice REAL,
      sales INTEGER
    ) `;
    await this.rdbStore!.executeSql(sql);
  }

  // 创建购物车表
  private async createCartTable(): Promise<void> {
    const sql = ` CREATE TABLE IF NOT EXISTS cart (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      productId INTEGER NOT NULL,
      name TEXT NOT NULL,
      imageUrl TEXT,
      price REAL,
      count INTEGER,
      isChecked INTEGER
    ) `;
    await this.rdbStore!.executeSql(sql);
  }

  // 查询数据
  async query(sql: string, args?: Array<string>): Promise<Array<relationalStore.ResultSet>> {
    if (!this.rdbStore) {
      return [];
    }
    const resultSet = await this.rdbStore.querySql(sql, args);
    const data: Array<relationalStore.ResultSet> = [];
    if (resultSet.goToFirstRow()) {
      do {
        data.push(resultSet);
      } while (resultSet.goToNextRow());
    }
    return data;
  }

  // 插入数据
  async insert(tableName: string, values: Record<string, any>): Promise<number> {
    if (!this.rdbStore) {
      return -1;
    }
    const rowId = await this.rdbStore.insert(tableName, values);
    return rowId;
  }

  // 更新数据
  async update(tableName: string, values: Record<string, any>, whereClause?: string, whereArgs?: Array<string>): Promise<number> {
    if (!this.rdbStore) {
      return 0;
    }
    const count = await this.rdbStore.update(tableName, values, whereClause, whereArgs);
    return count;
  }

  // 删除数据
  async delete(tableName: string, whereClause?: string, whereArgs?: Array<string>): Promise<number> {
    if (!this.rdbStore) {
      return 0;
    }
    const count = await this.rdbStore.delete(tableName, whereClause, whereArgs);
    return count;
  }
}
2. SQLite 应用

修改 entry/src/main/ets/services/ProductService.ets:

import { HttpUtils } from '../utils/HttpUtils';
import { GoodsModel } from '../models/HomeModel';
import { SQLiteUtils } from '../utils/SQLiteUtils';

// 商品服务
export class ProductService {
  // ... 其他方法

  // 获取商品列表(先从本地数据库获取,再从网络获取)
  async getProductList(): Promise<Array<GoodsModel>> {
    // 先从本地数据库获取
    const localData = await this.getProductListFromLocal();
    if (localData.length > 0) {
      return localData;
    }
    // 本地数据库无数据,从网络获取
    const remoteData = await this.getProductListFromRemote();
    // 将网络数据存入本地数据库
    await this.saveProductListToLocal(remoteData);
    return remoteData;
  }

  // 从本地数据库获取商品列表
  private async getProductListFromLocal(): Promise<Array<GoodsModel>> {
    const sql = 'SELECT * FROM product';
    const resultSet = await SQLiteUtils.getInstance().query(sql);
    const data: Array<GoodsModel> = [];
    resultSet.forEach(row => {
      data.push({
        id: row.getDouble(row.getColumnIndex('id')),
        name: row.getString(row.getColumnIndex('name')),
        imageUrl: row.getString(row.getColumnIndex('imageUrl')),
        price: row.getDouble(row.getColumnIndex('price')),
        originalPrice: row.getDouble(row.getColumnIndex('originalPrice')),
        sales: row.getDouble(row.getColumnIndex('sales'))
      });
    });
    return data;
  }

  // 从网络获取商品列表
  private async getProductListFromRemote(): Promise<Array<GoodsModel>> {
    const response = await HttpUtils.getInstance().get<Array<GoodsModel>>('/api/products');
    return response;
  }

  // 将商品列表存入本地数据库
  private async saveProductListToLocal(data: Array<GoodsModel>): Promise<void> {
    for (const item of data) {
      await SQLiteUtils.getInstance().insert('product', {
        id: item.id,
        name: item.name,
        imageUrl: item.imageUrl,
        price: item.price,
        originalPrice: item.originalPrice,
        sales: item.sales
      });
    }
  }
}

四、用户体验优化

4.1 加载动画

创建 entry/src/main/ets/components/LoadingComponent.ets:

@Component
export struct LoadingComponent {
  @Prop isLoading: boolean = false;

  build() {
    Column({ space: 16 }) {
      Progress({ value: 0, total: 100, type: ProgressType.ScaleRing })
        .width(60)
        .height(60)
        .style({ strokeWidth: 5, scaleCount: 12, duration: 1000 });
      Text('加载中...').fontSize(14).textColor('#666666');
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .visible(this.isLoading);
  }
}
4.2 错误处理

创建 entry/src/main/ets/components/ErrorComponent.ets:

@Component
export struct ErrorComponent {
  @Prop isError: boolean = false;
  @Prop errorMessage: string = '请求失败';
  onRetry: () => void;

  build() {
    Column({ space: 16 }) {
      Image($r('app.media.error')).width(80).height(80).objectFit(ImageFit.Contain);
      Text(this.errorMessage).fontSize(14).textColor('#666666');
      Button('重试').width(120).height(48).backgroundColor('#007DFF').onClick(() => this.onRetry());
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .visible(this.isError);
  }
}

五、项目运行与效果验证

5.1 项目配置
1. 配置 API 地址

在 entry/src/main/ets/utils/HttpUtils.ets 中替换为你的真实 API 地址:

const HTTP_CONFIG = {
  baseUrl: 'https://your-api-address.com', // 替换为你的 API 地址
  // ...
};
2. 初始化数据持久化

在 entry/src/main/ets/entryability/EntryAbility.ts 中初始化 Preferences 和 SQLite:

import { PreferencesUtils } from '../utils/PreferencesUtils';
import { SQLiteUtils } from '../utils/SQLiteUtils';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    // 初始化 Preferences
    PreferencesUtils.getInstance().init(this.context);
    // 初始化 SQLite
    SQLiteUtils.getInstance().init(this.context);
  }
  // ...
}
5.2 项目运行
  1. 在 DevEco Studio 中点击「Run」按钮;
  2. 选择调试设备,点击「OK」;
  3. 等待编译安装完成,应用会自动在设备上启动。

效果验证:

  • 商品列表网络请求:从真实 API 获取商品数据,支持本地缓存;
  • 用户信息网络请求:实现用户登录、注册、个人信息查询;
  • 网络状态检测:在无网络时显示网络状态提示;
  • 加载动画:商品列表加载时显示环形进度条;
  • 错误处理:请求失败时显示错误信息与重试按钮。

目录

  1. 鸿蒙 APP 开发:网络请求与数据持久化
  2. 核心内容
  3. 一、网络请求基础
  4. 1.1 鸿蒙 HTTP 请求库
  5. 1.2 实战:HTTP 请求库配置
  6. 1. 配置网络权限
  7. 2. 网络请求工具类
  8. 二、网络请求实战
  9. 2.1 业务服务实现
  10. 1. 商品服务
  11. 2. 用户服务
  12. 2.2 网络状态检测
  13. 1. 网络状态服务
  14. 2. 网络状态组件
  15. 三、数据持久化实战
  16. 3.1 数据持久化分类
  17. 3.2 实战:Preferences 存储
  18. 1. Preferences 工具类
  19. 2. Preferences 应用
  20. 3.3 实战:SQLite 存储
  21. 1. SQLite 数据库管理类
  22. 2. SQLite 应用
  23. 四、用户体验优化
  24. 4.1 加载动画
  25. 4.2 错误处理
  26. 五、项目运行与效果验证
  27. 5.1 项目配置
  28. 1. 配置 API 地址
  29. 2. 初始化数据持久化
  30. 5.2 项目运行

更多推荐文章

查看全部
  • C++ 智能指针:彻底解决内存泄漏问题
  • Vue3 集成腾讯云人脸核身功能教程及示例
  • Android 系统层 C++与 JNI 核心开发:AI 视频生成实践
  • Python 与 PyCharm 环境搭建实战指南
  • Chatbot UI:开源 AI 聊天应用框架
  • RabbitMQ 分布式系统实战:从安装部署到 C++ 调用详解
  • LeetCode 744. 寻找比目标字母大的最小字母 - 遍历解法
  • MySQL 数据表删除:DROP 与 TRUNCATE 实战指南
  • 前端流式输出技术:原理与实战指南
  • YOLOv3 C++ DLL 调用与 CUDA 依赖配置
  • 集群中继无人机应急通信双层多目标协同优化部署
  • VR 眼镜与自动验光仪的光学成像原理及视网膜适配技术
  • Git 多用户提交身份配置与切换方法
  • Python 闭包深度解密:当变量捕获遇见 nonlocal 的优雅与陷阱
  • Java AI 全流程开发指南:从需求到部署
  • 国企合同工三年的工作回忆与思考
  • OpenClaw 大龙虾机器人本地部署与配置指南
  • 基于 SpringBoot+Vue 的动漫视频分享与交流平台设计与实现
  • 逻辑派 FPGA-G1 开发板 6 层 PCB 全流程设计总结
  • C++ 程序打包成 SO 库并调用的完整指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online