【HarmonyOS】鸿蒙应用开发实战指南:构建网络数据列表应用

鸿蒙应用开发实战指南:构建网络数据列表应用

前言:本文从零开始,详细介绍如何使用HarmonyOS ArkTS语言开发一个具备网络请求和数据列表展示功能的应用。涵盖工程搭建、网络封装、UI开发、错误处理等核心知识点,适合鸿蒙开发入门者学习参考。

一、开发环境准备

1.1 必备软件清单

软件 版本要求 用途 下载地址
Node.js 16.x+ JavaScript运行环境 nodejs.org
DevEco Studio 4.0+ 鸿蒙官方IDE developer.huawei.com
Git 最新版 版本控制工具 git-scm.com

1.2 Git全局配置

bash 复制代码
# 配置用户信息
git config --global user.name "YourName"
git config --global user.email "your.email@example.com"

# 配置默认分支名
git config --global init.defaultBranch main

# 配置凭证缓存(避免频繁输入密码)
git config --global credential.helper store

1.3 代码仓库创建

在Gitee/AtomGit等平台创建新仓库:

仓库配置建议

  • 仓库名:harmonyos-network-demo
  • 可见性:公开
  • 许可证:MIT
  • 初始化选项:添加README、.gitignore(选择OpenHarmony模板)

1.4 本地仓库初始化

bash 复制代码
# 克隆仓库
git clone https://gitee.com/your-username/harmonyos-network-demo.git
cd harmonyos-network-demo

# 或本地初始化后关联远程
git init
git add .
git commit -m "chore: 初始化鸿蒙网络请求示例项目"
git branch -M main
git remote add origin https://gitee.com/your-username/harmonyos-network-demo.git
git push -u origin main

二、工程创建与目录结构

2.1 创建鸿蒙工程

  1. 打开DevEco Studio,点击「Create Project」
  2. 选择「Empty Ability」模板
  3. 配置工程信息:
    • 工程名:HarmonyoNetworkList
    • 包名:com.example.networklist
    • 保存位置:选择刚才克隆的仓库目录
    • SDK版本:API 10+
    • 设备类型:Phone

2.2 推荐目录结构

复制代码
HarmonyoNetworkList/
├── entry/
│   └── src/
│       └── main/
│           ├── ets/                    # ArkTS源码目录
│           │   ├── entryability/       # Ability入口
│           │   ├── pages/              # 页面目录
│           │   ├── model/              # 数据模型
│           │   ├── utils/              # 工具类
│           │   └── common/             # 公共资源
│           │       ├── constants/      # 常量定义
│           │       └── styles/         # 样式配置
│           ├── resources/              # 资源文件
│           │   ├── base/              # 基础资源
│           │   │   ├── element/       # 元素资源
│           │   │   ├── media/         # 媒体资源
│           │   │   └── profile/       # 配置文件
│           │   └── rawfile/           # 原始文件
│           └── module.json5           # 模块配置
├── oh-package.json5                    # 依赖管理
├── build-profile.json5                 # 构建配置
└── app.json5                           # 应用配置

三、核心配置文件详解

3.1 依赖管理(oh-package.json5)

json5 复制代码
{
  "name": "entry",
  "version": "1.0.1",
  "description": "HarmonyOS网络请求与列表展示示例",
  "main": "",
  "author": "",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {
    "@ohos/hypium": "1.0.16"
  }
}

3.2 模块配置(module.json5)

json5 复制代码
{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "default",
      "tablet"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:app_icon",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:icon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "$string:internet_permission_reason",
        "usedScene": {
          "abilities": [
            "EntryAbility"
          ],
          "when": "inuse"
        }
      }
    ]
  }
}

3.3 页面路由配置(main_pages.json)

json5 复制代码
{
  "src": [
    "pages/TaskListPage"
  ]
}

3.4 应用级配置(app.json5)

json5 复制代码
{
  "app": {
    "bundleName": "com.example.networklist",
    "vendor": "example",
    "versionCode": 1000000,
    "versionName": "1.0.0",
    "icon": "$media:app_icon",
    "label": "$string:app_name",
    "description": "$string:app_description",
    "targetSDKVersion": 10,
    "apiReleaseType": "Release"
  }
}

3.5 字符串资源配置

json5 复制代码
// resources/base/element/string.json
{
  "string": [
    {
      "name": "app_name",
      "value": "任务清单"
    },
    {
      "name": "app_description",
      "value": "基于HarmonyOS的网络请求与列表展示示例"
    },
    {
      "name": "module_desc",
      "value": "网络请求与数据列表示例模块"
    },
    {
      "name": "EntryAbility_desc",
      "value": "任务清单应用入口"
    },
    {
      "name": "EntryAbility_label",
      "value": "任务清单"
    },
    {
      "name": "internet_permission_reason",
      "value": "需要网络权限以获取任务数据"
    },
    {
      "name": "loading_text",
      "value": "加载中..."
    },
    {
      "name": "error_text",
      "value": "加载失败,请重试"
    },
    {
      "name": "retry_text",
      "value": "重试"
    },
    {
      "name": "empty_text",
      "value": "暂无数据"
    }
  ]
}

3.6 颜色资源配置

json5 复制代码
// resources/base/element/color.json
{
  "color": [
    {
      "name": "start_window_background",
      "value": "#FFFFFF"
    },
    {
      "name": "primary_color",
      "value": "#0A59F7"
    },
    {
      "name": "background_color",
      "value": "#F5F5F5"
    },
    {
      "name": "card_background",
      "value": "#FFFFFF"
    },
    {
      "name": "text_primary",
      "value": "#182431"
    },
    {
      "name": "text_secondary",
      "value": "#99182431"
    },
    {
      "name": "divider_color",
      "value": "#E5E5E5"
    },
    {
      "name": "success_color",
      "value": "#00C853"
    },
    {
      "name": "error_color",
      "value": "#FF5252"
    }
  ]
}

四、数据模型定义

4.1 任务数据模型

typescript 复制代码
// entry/src/main/ets/model/TaskModel.ets
/**
 * 任务数据项模型
 */
export interface TaskItem {
  id: number;           // 任务ID
  title: string;        // 任务标题
  completed: boolean;   // 完成状态
  userId: number;       // 用户ID
}

/**
 * 网络响应基类
 */
export interface ApiResponse<T> {
  data: T;              // 响应数据
  code: number;         // 响应码
  message: string;      // 响应消息
}

/**
 * 列表响应数据
 */
export interface ListResponse<T> {
  items: T[];           // 数据列表
  total: number;        // 总数量
  page: number;         // 当前页码
  pageSize: number;     // 每页大小
}

4.2 常量定义

typescript 复制代码
// entry/src/main/ets/common/constants/ApiConstants.ets
/**
 * API常量定义
 */
export class ApiConstants {
  // 基础URL
  private static readonly BASE_URL = 'https://jsonplaceholder.typicode.com';

  // API端点
  static readonly TASKS_ENDPOINT = '/todos';
  static readonly TASK_DETAIL_ENDPOINT = (id: number) => `/todos/${id}`;
  static readonly USER_TASKS_ENDPOINT = (userId: number) => `/todos?userId=${userId}`;

  // 完整URL构建
  static getFullUrl(endpoint: string): string {
    return `${this.BASE_URL}${endpoint}`;
  }

  // 超时时间(毫秒)
  static readonly CONNECT_TIMEOUT = 10000;
  static readonly READ_TIMEOUT = 15000;
}

/**
 * 业务常量
 */
export class BusinessConstants {
  // 每页加载数量
  static readonly PAGE_SIZE = 20;

  // 状态码
  static readonly SUCCESS_CODE = 200;
  static readonly ERROR_CODE = -1;

  // 缓存时间(秒)
  static readonly CACHE_DURATION = 300;
}

五、网络请求封装

5.1 HTTP请求工具类

typescript 复制代码
// entry/src/main/ets/utils/HttpUtil.ets
import http from '@ohos.net.http';
import { BusinessConstants } from '../common/constants/ApiConstants';

/**
 * HTTP请求配置
 */
interface RequestConfig {
  method?: http.RequestMethod;
  header?: Record<string, string>;
  readTimeout?: number;
  connectTimeout?: number;
  extraData?: string | Object | ArrayBuffer;
}

/**
 * HTTP响应数据
 */
interface HttpResponse<T> {
  data: T;
  statusCode: number;
  headers: Record<string, string>;
}

/**
 * HTTP请求工具类
 */
export class HttpUtil {
  /**
   * GET请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 请求配置
   */
  static async get<T>(
    url: string,
    params?: Record<string, string>,
    config?: RequestConfig
  ): Promise<HttpResponse<T>> {
    // 构建带参数的URL
    let fullUrl = url;
    if (params && Object.keys(params).length > 0) {
      const queryString = Object.keys(params)
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
        .join('&');
      fullUrl = `${url}?${queryString}`;
    }

    return this.request<T>(fullUrl, {
      method: http.RequestMethod.GET,
      readTimeout: BusinessConstants.CONNECT_TIMEOUT,
      connectTimeout: BusinessConstants.READ_TIMEOUT,
      ...config
    });
  }

  /**
   * POST请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   */
  static async post<T>(
    url: string,
    data?: Object | string,
    config?: RequestConfig
  ): Promise<HttpResponse<T>> {
    return this.request<T>(url, {
      method: http.RequestMethod.POST,
      extraData: data,
      readTimeout: BusinessConstants.READ_TIMEOUT,
      connectTimeout: BusinessConstants.CONNECT_TIMEOUT,
      ...config
    });
  }

  /**
   * 通用请求方法
   * @param url 请求地址
   * @param config 请求配置
   */
  private static async request<T>(
    url: string,
    config: RequestConfig = {}
  ): Promise<HttpResponse<T>> {
    // 创建HTTP请求对象
    const httpRequest = http.createHttp();

    try {
      // 设置默认请求头
      const defaultHeaders: Record<string, string> = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      };

      // 合并请求头
      const headers = {
        ...defaultHeaders,
        ...config.header
      };

      // 发起请求
      const response = await httpRequest.request(url, {
        method: config.method || http.RequestMethod.GET,
        header: headers,
        readTimeout: config.readTimeout || 15000,
        connectTimeout: config.connectTimeout || 10000,
        extraData: config.extraData
      });

      // 解析响应数据
      let responseData: T;
      const contentType = response.headers?.['Content-Type'] || '';
      const responseType = response.responseType;

      switch (responseType) {
        case http.HttpResponseType.STRING:
          if (contentType.includes('application/json')) {
            responseData = JSON.parse(response.result as string) as T;
          } else {
            responseData = response.result as T;
          }
          break;
        case http.HttpResponseType.ARRAY_BUFFER:
          responseData = response.result as T;
          break;
        default:
          responseData = response.result as T;
      }

      return {
        data: responseData,
        statusCode: response.responseCode,
        headers: response.headers
      };

    } catch (error) {
      throw new Error(`请求失败: ${error.message || error}`);
    } finally {
      // 销毁请求对象
      httpRequest.destroy();
    }
  }
}

5.2 任务数据服务

typescript 复制代码
// entry/src/main/ets/utils/TaskService.ets
import { HttpUtil } from './HttpUtil';
import { TaskItem } from '../model/TaskModel';
import { ApiConstants } from '../common/constants/ApiConstants';

/**
 * 任务数据服务类
 */
export class TaskService {
  /**
   * 获取所有任务列表
   */
  static async getAllTasks(): Promise<TaskItem[]> {
    const url = ApiConstants.getFullUrl(ApiConstants.TASKS_ENDPOINT);
    const response = await HttpUtil.get<TaskItem[]>(url);
    return response.data;
  }

  /**
   * 获取单个任务详情
   * @param taskId 任务ID
   */
  static async getTaskDetail(taskId: number): Promise<TaskItem> {
    const url = ApiConstants.getFullUrl(ApiConstants.TASK_DETAIL_ENDPOINT(taskId));
    const response = await HttpUtil.get<TaskItem>(url);
    return response.data;
  }

  /**
   * 获取指定用户的任务
   * @param userId 用户ID
   */
  static async getUserTasks(userId: number): Promise<TaskItem[]> {
    const url = ApiConstants.getFullUrl(ApiConstants.USER_TASKS_ENDPOINT(userId));
    const response = await HttpUtil.get<TaskItem[]>(url);
    return response.data;
  }

  /**
   * 按完成状态筛选任务
   * @param completed 是否完成
   */
  static async getTasksByStatus(completed: boolean): Promise<TaskItem[]> {
    const url = ApiConstants.getFullUrl(ApiConstants.TASKS_ENDPOINT);
    const response = await HttpUtil.get<TaskItem[]>(url, { completed: String(completed) });
    return response.data;
  }
}

六、UI组件开发

6.1 任务列表页面

typescript 复制代码
// entry/src/main/ets/pages/TaskListPage.ets
import { TaskItem } from '../model/TaskModel';
import { TaskService } from '../utils/TaskService';
import promptAction from '@ohos.promptAction';

/**
 * 任务状态枚举
 */
enum LoadState {
  IDLE = 'idle',
  LOADING = 'loading',
  SUCCESS = 'success',
  ERROR = 'error'
}

/**
 * 任务列表页面
 */
@Entry
@Component
struct TaskListPage {
  // 任务列表数据
  @State private taskList: TaskItem[] = [];

  // 加载状态
  @State private loadState: LoadState = LoadState.IDLE;

  // 错误信息
  @State private errorMessage: string = '';

  // 是否正在下拉刷新
  @State private isRefreshing: boolean = false;

  /**
   * 页面即将出现时加载数据
   */
  aboutToAppear(): void {
    this.loadTaskData();
  }

  /**
   * 加载任务数据
   */
  private async loadTaskData(): Promise<void> {
    this.loadState = LoadState.LOADING;
    this.errorMessage = '';

    try {
      const tasks = await TaskService.getAllTasks();
      this.taskList = tasks;
      this.loadState = LoadState.SUCCESS;
    } catch (error) {
      this.errorMessage = error.message || '加载失败,请重试';
      this.loadState = LoadState.ERROR;
      console.error(`[TaskListPage] 加载失败: ${this.errorMessage}`);
    }
  }

  /**
   * 下拉刷新
   */
  private async onRefresh(): Promise<void> {
    this.isRefreshing = true;
    await this.loadTaskData();
    this.isRefreshing = false;
  }

  /**
   * 重试加载
   */
  private onRetry(): void {
    this.loadTaskData();
  }

  /**
   * 任务项点击事件
   */
  private onTaskClick(task: TaskItem): void {
    promptAction.showToast({
      message: `任务: ${task.title}\n状态: ${task.completed ? '已完成' : '进行中'}`,
      duration: 2000
    });
  }

  /**
   * 切换任务完成状态
   */
  private toggleTaskStatus(task: TaskItem): void {
    task.completed = !task.completed;
    // 更新UI
    const index = this.taskList.findIndex(item => item.id === task.id);
    if (index !== -1) {
      this.taskList.splice(index, 1, { ...task });
    }
  }

  /**
   * 构建加载中UI
   */
  @Builder
  private LoadingBuilder() {
    Column() {
      LoadingProgress()
        .width(48)
        .height(48)
        .color($r('app.color.primary_color'))

      Text($r('app.string.loading_text'))
        .fontSize(16)
        .fontColor($r('app.color.text_secondary'))
        .margin({ top: 16 })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  /**
   * 构建错误UI
   */
  @Builder
  private ErrorBuilder() {
    Column({ space: 16 }) {
      Image($r('app.media.ic_error'))
        .width(80)
        .height(80)
        .fillColor($r('app.color.error_color'))

      Text(this.errorMessage || $r('app.string.error_text'))
        .fontSize(16)
        .fontColor($r('app.color.text_secondary'))
        .textAlign(TextAlign.Center)

      Button($r('app.string.retry_text'))
        .onClick(() => this.onRetry())
        .type(ButtonType.Capsule)
        .backgroundColor($r('app.color.primary_color'))
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .padding(24)
  }

  /**
   * 构建空数据UI
   */
  @Builder
  private EmptyBuilder() {
    Column({ space: 16 }) {
      Image($r('app.media.ic_empty'))
        .width(120)
        .height(120)
        .fillColor($r('app.color.text_secondary'))

      Text($r('app.string.empty_text'))
        .fontSize(16)
        .fontColor($r('app.color.text_secondary'))
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  /**
   * 构建任务项UI
   */
  @Builder
  private TaskItemBuilder(task: TaskItem, index: number) {
    Row() {
      // 状态图标
      Image(task.completed ? $r('app.media.ic_check_circle') : $r('app.media.ic_radio_unchecked'))
        .width(24)
        .height(24)
        .fillColor(task.completed ? $r('app.color.success_color') : $r('app.color.text_secondary'))
        .margin({ right: 12 })

      // 任务信息
      Column({ space: 4 }) {
        Text(task.title)
          .fontSize(16)
          .fontColor($r('app.color.text_primary'))
          .maxLines(2)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .decoration({
            type: task.completed ? TextDecorationType.LineThrough : TextDecorationType.None
          })

        Text(`ID: ${task.id} | 用户: ${task.userId}`)
          .fontSize(12)
          .fontColor($r('app.color.text_secondary'))
      }
      .alignItems(HorizontalAlign.Start)
      .layoutWeight(1)

      // 箭头图标
      Image($r('app.media.ic_arrow_right'))
        .width(16)
        .height(16)
        .fillColor($r('app.color.text_secondary'))
    }
    .width('100%')
    .padding(16)
    .backgroundColor($r('app.color.card_background'))
    .borderRadius(8)
    .margin({ bottom: 8 })
    .onClick(() => this.onTaskClick(task))
    .gesture(
      LongPressGesture({ repeat: false })
        .onAction(() => {
          this.toggleTaskStatus(task);
        })
    )
  }

  /**
   * 构建页面UI
   */
  build() {
    Column() {
      // 标题栏
      Row() {
        Text('任务清单')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .fontColor($r('app.color.text_primary'))
      }
      .width('100%')
      .height(56)
      .padding({ left: 16, right: 16 })
      .backgroundColor($r('app.color.card_background'))

      // 内容区域
      if (this.loadState === LoadState.LOADING) {
        this.LoadingBuilder()
      } else if (this.loadState === LoadState.ERROR) {
        this.ErrorBuilder()
      } else if (this.taskList.length === 0) {
        this.EmptyBuilder()
      } else {
        // 任务列表
        List({ space: 0 }) {
          ForEach(this.taskList, (task: TaskItem, index: number) => {
            ListItem() {
              this.TaskItemBuilder(task, index)
            }
          }, (task: TaskItem) => task.id.toString())
        }
        .width('100%')
        .layoutWeight(1)
        .padding({ left: 16, right: 16, top: 8 })
        .scrollBar(BarState.Auto)
        .edgeEffect(EdgeEffect.Spring)
      }

      // 统计信息
      if (this.loadState === LoadState.SUCCESS && this.taskList.length > 0) {
        Row() {
          Text(`共 ${this.taskList.length} 条任务`)
            .fontSize(14)
            .fontColor($r('app.color.text_secondary'))

          Blank()

          Text(`已完成: ${this.taskList.filter(t => t.completed).length}`)
            .fontSize(14)
            .fontColor($r('app.color.success_color'))
        }
        .width('100%')
        .height(48)
        .padding({ left: 16, right: 16 })
        .backgroundColor($r('app.color.card_background'))
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.background_color'))
  }
}

6.2 样式配置类

typescript 复制代码
// entry/src/main/ets/common/styles/AppStyles.ets
/**
 * 应用样式配置
 */
export class AppStyles {
  // 间距
  static readonly SPACING = {
    XS: 4,
    SM: 8,
    MD: 12,
    LG: 16,
    XL: 20,
    XXL: 24
  };

  // 字体大小
  static readonly FONT_SIZE = {
    XS: 12,
    SM: 14,
    MD: 16,
    LG: 18,
    XL: 20,
    XXL: 24
  };

  // 圆角
  static readonly RADIUS = {
    SM: 4,
    MD: 8,
    LG: 12,
    XL: 16,
    CIRCLE: 999
  };

  // 阴影
  static readonly SHADOW = {
    SM: {
      radius: 4,
      color: '#1A000000',
      offsetX: 0,
      offsetY: 2
    },
    MD: {
      radius: 8,
      color: '#1A000000',
      offsetX: 0,
      offsetY: 4
    },
    LG: {
      radius: 16,
      color:'#1A000000',
      offsetX: 0,
      offsetY: 8
    }
  };
}

七、常见问题与解决方案

7.1 网络请求相关

问题1:网络请求失败提示权限不足

复制代码
错误信息: Permission denial

解决方案:检查module.json5中是否正确配置网络权限

json5 复制代码
"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "reason": "$string:internet_permission_reason",
    "usedScene": {
      "abilities": ["EntryAbility"],
      "when": "inuse"
    }
  }
]

问题2:HTTPS证书校验失败

解决方案:在开发阶段可临时忽略证书校验(生产环境不推荐)

typescript 复制代码
httpRequest.request(url, {
  // 使用http协议仅用于开发测试
  // 生产环境必须使用https并正确配置证书
})

7.2 UI渲染相关

问题3:列表数据更新后UI不刷新

解决方案:确保使用@State装饰状态变量,更新时触发刷新

typescript 复制代码
// 错误做法
this.taskList[index].completed = true;

// 正确做法
this.taskList.splice(index, 1, { ...task, completed: true });

问题4:ForEach渲染警告:需要唯一的key标识

解决方案:确保ForEach的第三个参数返回唯一标识

typescript 复制代码
ForEach(this.taskList, (task: TaskItem) => {
  ListItem() { ... }
}, (task: TaskItem) => task.id.toString())  // 使用唯一ID作为key

7.3 资源引用相关

问题5:资源引用报错"Resource is not defined"

解决方案:使用$r()语法引用资源

typescript 复制代码
// 错误写法
Text('加载中')

// 正确写法
Text($r('app.string.loading_text'))

7.4 Git操作相关

问题6:推送时提示"remote rejected"

解决方案:

bash 复制代码
# 拉取远程最新代码
git pull origin main --rebase

# 解决冲突后推送
git push origin main

问题7:提交时报错"nothing to commit"

解决方案:检查文件状态

bash 复制代码
# 查看文件状态
git status

# 添加文件
git add .

# 提交
git commit -m "feat: 添加任务列表功能"

八、测试与验证

8.1 模拟器运行

  1. 打开Device Manager
  2. 创建Phone模拟器(API 10+)
  3. 选择模拟器,点击运行按钮

8.2 功能验证清单

  • 应用启动正常,显示任务列表页面
  • 首次加载显示加载状态
  • 网络请求成功,显示任务列表
  • 点击任务项显示详情提示
  • 长按任务项切换完成状态
  • 下拉刷新功能正常
  • 错误状态显示正确,重试功能可用
  • 空数据状态显示正确
  • 统计信息正确显示

8.3 日志记录

typescript 复制代码
// 添加日志标签
const TAG = '[TaskListPage]';

// 使用console记录日志
console.log(`${TAG} 加载数据`);
console.error(`${TAG} 加载失败: ${error.message}`);
console.warn(`${TAG} 数据为空`);

九、代码提交规范

9.1 提交信息格式

遵循 Conventional Commits 规范:

复制代码
<type>(<scope>): <subject>

<body>

<footer>

9.2 常用提交类型

类型 说明 示例
feat 新功能 feat(task): 添加任务列表功能
fix 问题修复 fix(network): 修复网络请求超时问题
docs 文档更新 docs(readme): 更新项目说明文档
style 代码格式 style(ui): 统一代码缩进格式
refactor 重构 refactor(service): 重构网络请求层
test 测试 test(api): 添加单元测试用例
chore 构建/工具 chore(deps): 更新依赖版本

9.3 提交示例

bash 复制代码
# 功能开发提交
git add .
git commit -m "feat(task): 实现任务列表数据加载与展示

- 添加网络请求封装类HttpUtil
- 添加任务数据服务TaskService
- 实现任务列表页面UI
- 支持下拉刷新和状态切换"

# 问题修复提交
git add .
git commit -m "fix(ui): 修复列表项点击事件无响应问题"

# 文档更新提交
git add README.md
git commit -m "docs(readme): 更新项目运行环境说明"

十、进阶优化方向

10.1 数据持久化

typescript 复制代码
// 使用Preferences存储本地数据
import dataPreferences from '@ohos.data.preferences';

export class LocalStorage {
  private static preferences: dataPreferences.Preferences | null = null;

  static async init(context: Context): Promise<void> {
    this.preferences = await dataPreferences.getPreferences(context, 'task_store');
  }

  static async saveTasks(tasks: TaskItem[]): Promise<void> {
    await this.preferences?.put('tasks', JSON.stringify(tasks));
    await this.preferences?.flush();
  }

  static async getTasks(): Promise<TaskItem[]> {
    const data = await this.preferences?.get('tasks', '[]');
    return JSON.parse(data as string);
  }
}

10.2 状态管理

typescript 复制代码
// 使用简单的状态管理
export class Store<T> {
  private state: T;
  private listeners: Array<(state: T) => void> = [];

  constructor(initialState: T) {
    this.state = initialState;
  }

  getState(): T {
    return this.state;
  }

  setState(newState: Partial<T>): void {
    this.state = { ...this.state, ...newState };
    this.notify();
  }

  subscribe(listener: (state: T) => void): () => void {
    this.listeners.push(listener);
    return () => {
      const index = this.listeners.indexOf(listener);
      this.listeners.splice(index, 1);
    };
  }

  private notify(): void {
    this.listeners.forEach(listener => listener(this.state));
  }
}

10.3 图片缓存

typescript 复制代码
// 简单的图片缓存管理
export class ImageCache {
  private static cache: Map<string, PixelMap> = new Map();

  static async get(url: string): Promise<PixelMap | null> {
    if (this.cache.has(url)) {
      return this.cache.get(url)!;
    }

    const imageSource = image.createImageSource(url);
    const pixelMap = await imageSource.createPixelMap();
    this.cache.set(url, pixelMap);
    return pixelMap;
  }

  static clear(): void {
    this.cache.clear();
  }
}

十一、总结

本文通过一个完整的网络请求与数据列表示例,介绍了HarmonyOS应用开发的核心流程:

11.1 核心知识点回顾

  1. 工程结构:合理的目录结构提升代码可维护性
  2. 配置文件:module.json5、oh-package.json5等核心配置
  3. 网络请求:基于@ohos.net.http的封装与使用
  4. UI组件:List、ForEach等组件实现列表展示
  5. 状态管理:@State装饰器的响应式更新机制
  6. 资源管理:字符串、颜色等资源的统一管理

11.2 关键收获

  • 掌握鸿蒙应用的基本开发流程
  • 了解网络请求的标准封装方式
  • 熟悉列表组件的最佳实践
  • 学会常见问题的排查与解决

11.3 下一步学习建议

  1. 深入学习ArkTS语法和特性
  2. 掌握更多UI组件的使用方法
  3. 学习应用数据持久化方案
  4. 了解分布式开发相关特性
  5. 探索性能优化技巧

参考资源:

相关推荐
马剑威(威哥爱编程)2 小时前
鸿蒙开发实战:玩转“智感握姿”——新闻列表左右手智能切换
华为·harmonyos·arkts·arkui·鸿蒙6
开开心心_Every2 小时前
电脑网速加速工具,无线有线叠加网络
网络·游戏·微信·pdf·电脑·excel·语音识别
霍格沃兹测试学院-小舟畅学2 小时前
Playwright测试超时管理:全局与局部超时设置
运维·服务器·网络
tryxr2 小时前
UDP 的报文结构和注意事项
网络·网络协议·udp
ITUnicorn2 小时前
【HarmonyOS6】从零实现随机数生成器
华为·harmonyos·arkts·鸿蒙·harmonyos6
码刘的极客手记2 小时前
vSphere 4.1 三大实用实战:vCenter 告警自动化、SIOC 无 License 启用及 Dropbox 存储运行 VM
运维·服务器·网络·自动化·虚拟机
BD同步2 小时前
双模PCIE总线授时板卡选型指南
大数据·网络·eclipse
崎岖Qiu2 小时前
【计算机网络 | 第二篇】三种交换方式和互联网的核心部分
网络·笔记·计算机网络·路由器
一位搞嵌入式的 genius2 小时前
深入理解浏览器中的 JavaScript:BOM、DOM、网络与性能优化
前端·javascript·网络·性能优化