【开源鸿蒙跨平台开发先锋训练营】[Day 3] React Native for OpenHarmony 实战:网络请求集成与高健壮性列表构建

📅 核心任务

本日重点攻克 OpenHarmony 环境下的网络通信 难关。不再是简单的 UI 堆砌,而是打通 "端-云" 链路,使用 React Native 技术栈(Axios + FlatList)实现一个具备 加载状态、错误兜底、下拉刷新 的完整数据列表,并在鸿蒙真机/模拟器上验证运行。


🚀 一、 破局:鸿蒙网络权限的"隐形墙"

在 Android 开发中我们习惯了 AndroidManifest.xml,而在 OpenHarmony 中,权限管理有着更严格的声明式规范。很多初学者代码写得天衣无缝,请求却永远发不出去,往往就是倒在了这一步。

1.1 权限声明机制

OpenHarmony 的权限管理位于 entry/src/main/module.json5 中。不同于 Android 的粗放,鸿蒙对权限有着明确的等级划分。

  • 什么是 module.json5? 它是鸿蒙应用的核心配置文件,类似于 Android 的 AndroidManifest.xml 或 iOS 的 Info.plist。它定义了应用的标识、组件、权限等关键信息。
  • requestPermissions 字段:这是一个数组,用来告诉系统"我需要哪些特权"。没有在这里声明的权限,应用运行时一律无法获取。

关键配置

打开 harmony/entry/src/main/module.json5,在 module 节点下新增 requestPermissions

json5 复制代码
"module": {
  // ... 其他配置
  "requestPermissions": [
    {
      "name": "ohos.permission.INTERNET", // 权限名称:允许访问互联网
      "reason": "$string:dependency_reason", // 申请理由:需要在多语言资源文件中定义,如果不涉及上架,暂可随意填写
      "usedScene": {
        "abilities": [
          "EntryAbility" // 适用的 Ability 组件,通常是主入口
        ],
        "when": "inuse" // 授权时机:inuse 表示使用时授权
      }
    }
  ]
}

1.2 ⚠️ 技术避坑指南:HTTP 明文流量限制

问题现象 :使用 http:// 接口请求失败,但 https:// 正常。
深度解析 :OpenHarmony 默认策略与 Android 高版本类似,禁止明文 HTTP 流量。这是为了防止中间人攻击,保护用户数据安全。
解决方案

  1. 首选:服务端升级 HTTPS(最安全)。现在 Let's Encrypt 等机构提供免费证书,升级 HTTPS 是行业标准。
  2. 临时方案 :在 module.json5deviceConfig (API 9 以前) 或相关网络安全配置文件中允许明文流量(不推荐生产环境)。但在 RNOH 当前适配中,底层网络库通常遵循系统默认安全策略,建议直接使用 HTTPS 避免不必要的底层调试。

🛠️ 二、 核心技术栈选型:Axios on Harmony

虽然 RN 提供了 fetch,但在企业级开发中,Axios 依然是首选。

2.1 为什么选择 Axios?

在 RNOH 架构中,JavaScript 端的网络请求最终会通过 RN 的 Bridge/TurboModule 调用到鸿蒙系统的网络能力。Axios 基于 XMLHttpRequest 适配,而 RNOH 完整实现了这一 API。

  • 拦截器(Interceptors):就像是快递站的安检员。发货前(请求拦截器)可以统一贴上标签(如 Token),收货时(响应拦截器)可以统一拆箱验货(处理 401 登出、统一错误提示)。
  • 自动转换 :Axios 会自动将服务器返回的 JSON 字符串转成 JS 对象,少写一行 response.json()
  • 取消请求:页面关闭时,如果请求还没回来,可以取消它,防止组件已销毁但请求回调还在执行导致的内存泄漏。

2.2 封装实战

不要直接在组件里调用 axios.get。建立 src/utils/request.ts,这样如果以后要换网络库,只需要改这一个文件。

typescript 复制代码
import axios from 'axios';
import { Alert, Platform } from 'react-native';

const instance = axios.create({
  baseURL: 'https://api.example.com', // 替换为实际 API
  timeout: 10000, // 超时时间:10秒,网络不好时不会一直卡住
});

// 响应拦截器:统一错误处理
instance.interceptors.response.use(
  response => response.data, // 直接返回数据部分,过滤掉 header 等信息
  error => {
    // 针对鸿蒙平台的特定错误日志
    // Platform.OS === 'harmony' 是 RNOH 特有的判断,用于区分鸿蒙平台
    if (Platform.OS === 'harmony') {
      console.error('[RNOH] Network Error:', error);
    }
    return Promise.reject(error);
  }
);

export default instance;

📊 三、 构建高健壮性数据列表

在鸿蒙设备上渲染长列表,性能是关键。我们使用 FlatList 并结合 TypeScript 进行类型约束。FlatList 是 RN 的高性能列表组件,它只渲染屏幕上可见的元素,看不见的会回收,非常适合长列表。

3.1 列表渲染策略

  • 防抖动 :网络请求尽量放在 useEffect 中。useEffect 就像是组件的"生命周期钩子",空数组 [] 意味着只在组件挂载时执行一次,避免每次渲染都发请求造成死循环。
  • 空状态兜底(Empty State) :网络慢或无数据时,不能白屏,要给用户反馈。ListEmptyComponent 属性就是专门干这个的。
  • Key 优化keyExtractor 必须唯一。React 需要用 key 来识别哪些元素改变了。如果 key 不唯一,Diff 算法就会混乱,导致鸿蒙 ArkUI 渲染性能下降,甚至 UI 错乱。

3.2 完整代码实现 (ProductList.tsx)

tsx 复制代码
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, ActivityIndicator, StyleSheet, RefreshControl } from 'react-native';
import request from '../utils/request';

// 定义数据结构接口,TS 的好处是写代码时就有提示
interface ItemData {
  id: string;
  title: string;
  desc: string;
}

const ProductList = () => {
  // useState: 管理组件内部状态
  const [data, setData] = useState<ItemData[]>([]); // 列表数据
  const [loading, setLoading] = useState(true); // 是否正在初次加载
  const [refreshing, setRefreshing] = useState(false); // 是否正在下拉刷新

  const fetchData = async () => {
    try {
      // 真实请求示例:
      // const res = await request.get('/products');
      // setData(res.list);
      
      // Mock 数据用于演示:模拟 1秒后返回数据
      setTimeout(() => {
        // Array.from 生成 20 条模拟数据
        setData(Array.from({ length: 20 }).map((_, i) => ({
            id: String(i),
            title: `鸿蒙跨端商品 ${i + 1}`,
            desc: 'React Native for OpenHarmony 运行验证'
        })));
        setLoading(false); // 停止 loading 转圈
        setRefreshing(false); // 停止下拉刷新转圈
      }, 1000);
    } catch (err) {
      console.error(err);
      setLoading(false);
      setRefreshing(false);
      // 实际项目中这里应该提示用户"网络错误"
    }
  };

  // 组件挂载完成后立即请求数据
  useEffect(() => {
    fetchData();
  }, []);

  // 下拉刷新触发的方法
  const onRefresh = () => {
    setRefreshing(true);
    fetchData();
  };

  // 首次加载时的 Loading 页面
  if (loading && !refreshing) {
    return <ActivityIndicator size="large" color="#0a59f7" style={styles.center} />;
  }

  return (
    <FlatList
      data={data}
      keyExtractor={(item) => item.id} // 告诉 RN 每一项的唯一 ID 是什么
      refreshControl={
        // 下拉刷新组件
        <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
      }
      renderItem={({ item }) => (
        // 每一行长什么样
        <View style={styles.item}>
          <Text style={styles.title}>{item.title}</Text>
          <Text style={styles.desc}>{item.desc}</Text>
        </View>
      )}
      ListEmptyComponent={
        // 没数据时显示什么
        <Text style={styles.emptyText}>暂无数据,请检查网络连接</Text>
      }
    />
  );
};

const styles = StyleSheet.create({
  center: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  item: { padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee' },
  title: { fontSize: 18, fontWeight: 'bold', color: '#333' },
  desc: { marginTop: 8, color: '#666' },
  emptyText: { textAlign: 'center', marginTop: 50, color: '#999' }
});

export default ProductList;

🔍 四、 深度排查与验证 (Troubleshooting)

在将代码部署到 OpenHarmony 真机/模拟器时,可能会遇到以下问题:

4.1 编译报错:Could not find "libRNOHApp.so"

现象 :引入新库后,C++ 链接失败。
分析 :React Native for OpenHarmony 包含 C++ 代码(原生模块)。如果你更新了依赖,原来的构建缓存可能和新依赖不匹配。
解决

  1. 清理构建 :运行 cd harmony && ./hvigorw.bat clean。这相当于把房子拆了重新盖,清除所有旧的构建产物。
  2. 同步依赖 :确保 oh-package.json5 中的依赖已同步。
  3. 重新 Sync:在 DevEco Studio 中点击 "Sync Project with Gradle Files" (或者类似的 Sync 按钮)。

4.2 运行时:Network Error 但其他 App 正常

分析

  • 权限未生效 :检查 module.json5 修改后是否重新安装 了 HAP?鸿蒙的热重载(Hot Reload)通常只更新 JS 代码,不更新配置文件。修改了 module.json5 必须重新点击 Run 按钮进行全量安装。
  • 时间不对:检查设备时间是否准确。HTTPS 协议需要校验 SSL 证书的有效期,如果设备时间还在 1970 年,证书校验就会失败,导致请求被拒绝。

📝 五、 代码提交与 Git 规范

完成验证后,推送到 AtomGit。Git 是团队协作的基石,规范的提交记录能让队友一眼看懂你干了什么。

bash 复制代码
# 1. 检查状态:看看修改了哪些文件
git status

# 2. 添加变更:把所有修改放入暂存区
git add .

# 3. 提交代码 (遵循 Commit Message 规范)
# 格式: feat(模块): 描述
# feat 表示新功能,fix 表示修复 bug
git commit -m "feat(network): 集成Axios并实现商品列表页
- 配置 module.json5 网络权限
- 封装 Axios 请求工具类
- 实现 FlatList 下拉刷新与空状态处理"

# 4. 推送到远程 dev 分支
git push origin dev

🌟 总结

今天我们跨越了 RNOH 开发的一个重要里程碑:与外部世界通信 。虽然代码层面主要是 JS,但底层的权限配置、网络策略、以及在鸿蒙设备上的实际表现,都体现了跨平台开发的特殊性------既要懂前端的灵动,也要懂原生的规矩

欢迎加入开源鸿蒙跨平台社区:

https://openharmonycrossplatform.csdn.net

相关推荐
秋91 小时前
从 Python 后端工程师转型 AI Engineer(AI 工程化)的完整补课清单(2026实战版)
开发语言·人工智能·python
lularible1 小时前
从沙子到车辙(7.4):《兰亭集序》的启示
开源·嵌入式·汽车电子
啦啦啦_99991 小时前
5. 迁移学习
人工智能·机器学习·迁移学习
A.说学逗唱的Coke1 小时前
【AI·Coding】TDD × SDD × AI Coding:从“测试驱动“到“规范驱动“的智能协作实践
人工智能·驱动开发·tdd
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【78】沙箱(Sandbox)
java·人工智能·spring
Soari2 小时前
开源项目解析 openmed —— 面向医疗智能应用的 OpenMed 开源平台
开源
tq10862 小时前
基于SLIP的防幻觉的指南
人工智能
听你说322 小时前
科技护航极限征程 三诺生物助力雄关330长城越野赛
大数据·科技·健康医疗
周航宇JoeZhou2 小时前
JB3-9-SpringAI(二)
java·ai·agent·多智能体·调度·智能体·观察
电商API_180079052472 小时前
bilibili关键字搜索视频列表|获取视频详情API调用示例
大数据·数据挖掘·网络爬虫·音视频