鸿蒙专家 发表于 2026-9-14 15:00:00

鸿蒙元服务ASCF弱网监听与网络状态检测适配实践

为什么要在元服务里处理网络状态

做元服务开发时,网络状态很容易被忽略,但它直接影响接口请求体验。用户在地铁里从 Wi-Fi 切到蜂窝,或信号变差进入弱网,如果没有处理,请求可能直接超时。ASCF 提供了 getNetworkType、getLocalIPAddress、onNetworkStatusChange、onNetworkWeakChange 等网络 API,可以覆盖网络类型获取、局域网 IP 获取、连接状态监听和弱网状态感知。

先分清 API 和权限

getNetworkType 用于获取当前网络类型;getLocalIPAddress 用于获取设备在局域网中的 IP 和子网掩码;onNetworkStatusChange 监听网络连接状态变化;onNetworkWeakChange 监听弱网状态变化。权限方面,getNetworkType 和 onNetworkStatusChange 需要 ohos.permission.GET_NETWORK_INFO,getLocalIPAddress 需要 ohos.permission.GET_WIFI_INFO,两者不要混用。

获取当前网络类型

最基础的用法是查询当前连接的是什么网络:


has.getNetworkType({
success: (res) => {
    console.info('当前网络类型:', res.networkType);
},
fail: (err) => {
    console.error('获取网络类型失败:', err);
}
});


networkType 返回字符串。需要注意,cellular 不会区分 4G 或 5G,它只表示当前使用的是移动数据,具体制式需要查其他 API。

获取局域网 IP 地址

getLocalIPAddress 可以拿到设备在局域网中的 IP 和子网掩码:


has.getLocalIPAddress({
success: (res) => {
    console.info('局域网 IP:', res.localip);
    console.info('子网掩码:', res.netmask);
},
fail: (err) => {
    console.error('获取 IP 失败:', err);
}
});


这个接口需要 ohos.permission.GET_WIFI_INFO,而且只有在连接 Wi-Fi 时才能拿到有效值。蜂窝网络下没有局域网概念,接口可能返回空或直接失败。它更适合局域网设备发现或 P2P 通信,普通业务开发一般用不到。

监听网络连接状态变化

用户使用过程中切换网络很常见,因此需要监听网络状态。注册方式如下:


const onNetworkStatusChange = (res) => {
console.info('网络状态变化:', res);
console.info('是否连接:', res.isConnected);
console.info('网络类型:', res.networkType);
};

has.onNetworkStatusChange(onNetworkStatusChange);


回调返回两个关键字段:isConnected 表示当前是否有网络连接,networkType 表示当前网络类型,取值与 getNetworkType 一致。不再需要监听时要移除:


has.offNetworkStatusChange(onNetworkStatusChange);


这里有一个常见坑:offNetworkStatusChange 必须传入与注册时同一个函数对象。如果注册时使用匿名函数,移除时再写一个匿名函数,并不是同一个引用,监听就移除不掉。


// 错误写法:这样移除不掉
has.onNetworkStatusChange((res) => { /* ... */ });
has.offNetworkStatusChange((res) => { /* ... */ });

// 正确写法:用变量保存
const handler = (res) => { /* ... */ };
has.onNetworkStatusChange(handler);
has.offNetworkStatusChange(handler);


监听弱网状态变化

onNetworkWeakChange 是 1.0.12 新增的,用于检测弱网:


const onNetworkWeakChange = (res) => {
console.info('弱网状态变化:', res);
console.info('是否弱网:', res.weakNet);
console.info('网络类型:', res.networkType);
};

has.onNetworkWeakChange(onNetworkWeakChange);


返回字段包括 weakNet,表示当前是否处于弱网状态;networkType 表示当前网络类型,但这里只会出现 cellular 和 wifi 两种。移除方式与网络状态监听相同:


has.offNetworkWeakChange(onNetworkWeakChange);


弱网检测的实际意义比较大。进入弱网后,可以降低图片质量、减少请求频率,或者提示用户当前网络较差。相比让用户一直等转圈,这种降级和反馈体验更好。

在页面生命周期里管理监听

实际项目中,可以在页面生命周期里注册和移除监听,并结合 getNetworkType 获取初始状态。核心思路是把回调函数挂到 this 上,用下划线前缀区分,便于在页面销毁时精确移除:


Page({
data: {
    networkType: '未知',
    isConnected: true,
    isWeakNet: false,
    localIP: '',
},
onReady() {
    this.getNetworkInfo();
},
onUnload() {
    this.removeListeners();
},
getNetworkInfo() {
    has.getNetworkType({
      success: (res) => {
      this.setData({ networkType: res.networkType });
      }
    });

    this._onNetworkStatusChange = (res) => {
      this.setData({
      isConnected: res.isConnected,
      networkType: res.networkType
      });
      if (!res.isConnected) {
      console.warn('网络已断开');
      }
    };
    has.onNetworkStatusChange(this._onNetworkStatusChange);

    this._onNetworkWeakChange = (res) => {
      this.setData({ isWeakNet: res.weakNet });
      if (res.weakNet) {
      console.warn('进入弱网状态');
      }
    };
    has.onNetworkWeakChange(this._onNetworkWeakChange);
},
getLocalIP() {
    has.getLocalIPAddress({
      success: (res) => {
      this.setData({ localIP: res.localip });
      },
      fail: (err) => {
      console.error('获取 IP 失败:', err);
      this.setData({ localIP: '获取失败' });
      }
    });
},
removeListeners() {
    if (this._onNetworkStatusChange) {
      has.offNetworkStatusChange(this._onNetworkStatusChange);
    }
    if (this._onNetworkWeakChange) {
      has.offNetworkWeakChange(this._onNetworkWeakChange);
    }
}
});


权限配置

在 module.json5 的 requestPermissions 中加入权限。若只使用 getNetworkType 和 onNetworkStatusChange,配置 ohos.permission.GET_NETWORK_INFO 即可;如果还要使用 getLocalIPAddress,再按需加入 ohos.permission.GET_WIFI_INFO。权限的 reason 和 usedScene 应按实际使用场景填写,避免声明无关权限。

几个容易踩的坑

弱网回调的 networkType 只有 cellular 和 wifi,不像 onNetworkStatusChange 那样种类多,因此不能通过弱网回调判断蓝牙等连接类型。offNetworkStatusChange 如果不传 callback 参数,会移除当前页面所有网络状态监听;如果页面里有多个监听函数,不传参调用会全部移除,线上代码应传具体函数引用。getLocalIPAddress 在蜂窝网络下返回空或失败,不要在移动数据环境下依赖它。networkType 在部分特殊网络环境,例如企业内网代理、特殊 VPN 配置下,可能返回 unknown;代码不能只处理 wifi 和 cellular,要对未知类型做兜底。

结合请求做弱网降级

只监听弱网还不够,业务层要响应。可以在请求封装里先判断网络状态:


function requestWithNetCheck(options) {
has.getNetworkType({
    success: (res) => {
      if (res.networkType === 'none') {
      console.warn('无网络连接,跳过请求');
      if (options.fail) {
          options.fail({ errMsg: '无网络连接' });
      }
      return;
      }
      has.request({
      url: options.url,
      method: options.method || 'GET',
      data: options.data,
      success: options.success,
      fail: options.fail
      });
    }
});
}


更进一步,可以在弱网状态下降低请求频率,例如把轮询间隔从 5 秒改成 30 秒,或取消非关键请求。这些逻辑不复杂,但对用户体验提升明显。

给用户可见的 UI 反馈

监听到网络变化后,除了业务降级,UI 也要给出反馈。例如在页面顶部显示网络状态提示条:


Page({
data: {
    showNetTip: false,
    netTipText: '',
    netTipType: 'warn',
},
onReady() {
    this._onNetworkStatusChange = (res) => {
      if (!res.isConnected) {
      this.setData({
          showNetTip: true,
          netTipText: '网络已断开,请检查网络连接',
          netTipType: 'error'
      });
      } else {
      this.setData({
          showNetTip: true,
          netTipText: '已恢复' + res.networkType + '网络',
          netTipType: 'success'
      });
      setTimeout(() => {
          this.setData({ showNetTip: false });
      }, 3000);
      }
    };
    has.onNetworkStatusChange(this._onNetworkStatusChange);
}
});


顶部提示条比直接弹 modal 框侵入性更小,不会打断用户操作。

多页面与全局监听

如果多个页面都需要监听网络状态,每个页面各自注册和移除即可。ASCF 的监听按页面隔离,页面销毁时会自动清理。若要做 App 级全局网络状态管理,可以在 app.js 的 onCreate 里注册全局监听,再通过事件总线或全局状态同步给各个页面:


App({
data: {
    globalNetworkType: 'unknown',
    globalIsConnected: true,
},
onCreate() {
    has.onNetworkStatusChange((res) => {
      this.data.globalNetworkType = res.networkType;
      this.data.globalIsConnected = res.isConnected;
      // 这里可以触发全局事件通知各页面
    });
}
});


不过大多数场景按页面管理就够了,除非元服务对网络依赖特别重,否则不必把监听架构做得太复杂。

兼容与总结

onNetworkWeakChange 是 1.0.12 才加入的,如果需要兼容低版本 ASCF,记得做降级处理,不要直接调用导致报错。总体来说,网络状态感知看起来简单,但做好权限区分、监听引用管理、弱网降级和 UI 反馈,就能明显改善弱网和切换网络场景下的用户体验。

热心网友5 发表于 2026-9-14 19:00:00

Re: 鸿蒙元服务ASCF弱网监听与网络状态检测适配实践

感谢分享,内容很实用。之前做元服务时确实容易只顾着接口请求,忽略网络状态变化,尤其是弱网场景,等到用户反馈一直转圈才去补。你提到的权限区分很关键,getNetworkType 和 onNetworkStatusChange 用 GET_NETWORK_INFO,getLocalIPAddress 用 GET_WIFI_INFO,这两个我之前也差点混着申请。offNetworkStatusChange 那个坑更深,匿名函数注册后再用匿名函数移除根本移不掉,页面销毁后回调还活着,容易出现 setData 到已销毁页面的问题,用 this 上挂变量、在 onUnload 里精确移除确实更稳。 弱网监听 onNetworkWeakChange 这一段也很有启发,进入弱网后做图片降级、减少请求频率、给用户明确提示,比一直等超时体验好很多。想请教一下,如果页面只是 onHide 而不是 onUnload,监听一般保留还是也移除?多个页面同时注册监听时,会不会有冲突或者重复回调的情况?整体总结得很到位,学到了。

热心网友3 发表于 2026-9-14 19:10:00

Re: 鸿蒙元服务ASCF弱网监听与网络状态检测适配实践

感谢分享,这篇把元服务里网络状态和弱网监听的几个关键点讲得很清楚。getNetworkType、getLocalIPAddress、onNetworkStatusChange、onNetworkWeakChange 的用途和权限区分很实用,特别是 GET_NETWORK_INFO 和 GET_WIFI_INFO 不能混用,以及 off 方法必须传注册时同一个函数对象这个坑,确实容易忽略。页面 onReady 注册、onUnload 移除并配合 getNetworkType 拿初始状态的写法也很顺,后面做弱网降级和用户提示就有依据了。想请教下,onNetworkWeakChange 在弱网恢复时会再回调一次把 weakNet 置回 false 吗?另外弱网监听里 networkType 只有 wifi 和 cellular,如果当前完全没连接,是不是就只靠 onNetworkStatusChange 的 isConnected 来判断?

热心网友2 发表于 2026-9-14 19:20:00

Re: 鸿蒙元服务ASCF弱网监听与网络状态检测适配实践

这篇整理挺实用的,尤其是把权限区分讲清楚了:getNetworkType 和 onNetworkStatusChange 用 GET_NETWORK_INFO,getLocalIPAddress 用 GET_WIFI_INFO,确实很容易混。还有 offNetworkStatusChange 必须传同一个函数对象这个坑,用变量保存回调这点很关键,匿名函数写法在实际项目里很容易导致监听移除不掉。 另外弱网监听 onNetworkWeakChange 这段也很有参考价值,进入弱网后做图片降级、降低请求频率或给用户提示,比一直转圈体验好很多。把监听注册和移除放到页面生命周期里管理,也符合元服务页面级资源释放的思路。 不过首帖末尾的页面示例好像没贴完,停在 isConnected 那里了。方便的话可以补一下 removeListeners 和弱网监听的完整写法,整体对做鸿蒙元服务网络适配帮助很大。
页: [1]
查看完整版本: 鸿蒙元服务ASCF弱网监听与网络状态检测适配实践