网络状态监听WiFi信息获取弱网提示、断网兜底方案几乎所有鸿蒙应用都要联网接口请求、图片加载、数据同步都依赖网络。但很多开发者只关注能不能请求成功忽略了网络状态变化的处理——用户切到地下车库WiFi断了页面还在转圈电梯里信号弱接口超时了也不提示。最后用户以为APP卡了直接退出。本文基于最新鸿蒙API把网络状态监听、WiFi信息获取、弱网提示和断网兜底的完整落地流程讲清楚代码可以直接复制到项目里跑。01 权限前置与网络状态监听网络监听需要先配置权限获取WiFi信息还需要定位权限因为WiFi位置信息涉及用户隐私。module.json5里需要声明两个权限requestPermissions:[{name:ohos.permission.GET_NETWORK_INFO,reason:$string:network_reason,usedScene:{abilities:[EntryAbility],when:inuse}},{name:ohos.permission.GET_WIFI_INFO,reason:$string:wifi_reason,usedScene:{abilities:[EntryAbility],when:inuse}}]GET_NETWORK_INFO用来监听网络状态变化GET_WIFI_INFO用来获取WiFi详细信息。如果还要扫描周边WiFi列表还需要加定位权限这里我们只获取当前连接的WiFi信息不需要扫描。网络状态监听的核心是netConnection对象注册回调后网络变化会自动通知import{connection}fromkit.NetworkKit;constnetConnconnection.createNetConnection();// 网络可用回调netConn.on(netAvailable,(data:connection.NetCapabilities){console.info(网络可用类型:,data.bearerTypes);// WiFi: BEARER_WIFI, 蜂窝: BEARER_CELLULAR});// 网络丢失回调断网netConn.on(netLost,(data:connection.NetHandle){console.info(网络已断开);// 这里触发断网兜底逻辑});// 网络能力变化回调弱网切换netConn.on(netCapabilitiesChange,(data:connection.NetCapabilities){console.info(网络能力变化:,data.bearerTypes);// 可以在这里判断是否从WiFi切到蜂窝});// 注册监听开始接收网络状态变化netConn.register(true);// 页面退出时记得反注册不然会内存泄漏// netConn.unregister();几个关键回调的触发时机netAvailable网络恢复可用时触发刚开机、从断网恢复都会走这里netLost网络完全断开时触发关WiFi、飞行模式、信号全丢netCapabilitiesChange网络类型切换时触发比如WiFi切到4G或者网络质量变化register(true)里的true表示立即返回一次当前网络状态不用等下次变化。02 获取当前网络类型与WiFi信息除了监听状态变化很多场景还需要主动获取当前网络的详细信息当前是WiFi还是蜂窝、WiFi信号强度是多少、SSID是什么。import{connection}fromkit.NetworkKit;import{wifiManager}fromkit.ConnectivityKit;// 获取当前默认网络asyncfunctiongetCurrentNetwork(){constnetHandleconnection.getDefaultNet();constcapabilitiesconnection.getNetCapabilities(netHandle);// 判断网络类型constisWificapabilities.bearerTypes.includes(connection.NetBearType.BEARER_WIFI);constisCellularcapabilities.bearerTypes.includes(connection.NetBearType.BEARER_CELLULAR);console.info(WiFi:,isWifi,蜂窝:,isCellular);return{isWifi,isCellular,capabilities};}WiFi详细信息通过wifiManager获取asyncfunctiongetWifiInfo(){constwifiwifiManager.getWifiInstance();// 先判断WiFi是否打开if(!wifi.isWifiActive()){console.info(WiFi未开启);returnnull;}constinfowifi.getLinkedInfo();console.info(WiFi名称:,info.ssid);console.info(信号强度:,info.rssi);// -50很好-80以下就是弱网console.info(连接速度:,info.linkSpeed);// 单位Mbpsconsole.info(频率:,info.frequency);// 2.4G还是5Greturninfo;}rssi是WiFi信号强度数值越大信号越好-50以上信号极好下载看视频无压力-50到-70信号良好正常使用没问题-70到-80信号偏弱加载图片会慢-80以下信号很差接口容易超时这个数值可以直接用来判断弱网不用自己算。03 弱网检测与提示实现弱网不是完全断网而是能用但很慢。用户感觉页面卡、图片加载不出来但又不知道是网络的问题。这时候主动给个提示体验会好很多。弱网判断可以从两个维度入手WiFi信号强度以及接口请求耗时。import{promptAction}fromkit.ArkUI;letisWeakNetwork:booleanfalse;// 根据WiFi信号判断弱网functioncheckWifiWeakness(rssi:number):boolean{// rssi低于-75就算弱网returnrssi-75;}// 接口请求超时统计连续超时就算弱网lettimeoutCount:number0;constMAX_TIMEOUT2;// 连续2次超时判定弱网functiononRequestSuccess(){timeoutCount0;}functiononRequestTimeout(){timeoutCount;if(timeoutCountMAX_TIMEOUT!isWeakNetwork){isWeakNetworktrue;promptAction.showToast({message:当前网络较慢建议切换网络});}}functiononNetworkRecover(){isWeakNetworkfalse;timeoutCount0;}弱网提示不要做成弹窗打断用户用顶部横幅或者轻量Toast就够了。用户知道网络不好自然会自己切换。弹窗太强硬反而引起反感。还有一个细节弱网时可以自动降低图片加载质量。比如列表页的缩略图弱网下加载低清版本WiFi下加载高清版本这样加载速度会快很多。04 断网兜底方案设计完全断网的时候不能让用户对着一个白屏或者转圈的加载页发呆。断网兜底的核心思路是检测到断网 → 显示兜底页面 → 网络恢复 → 自动重试。页面级别的断网兜底可以封装成一个通用组件EntryComponentstruct NetworkGuard{StateisOffline:booleanfalse;privatenetConn:connection.NetConnectionconnection.createNetConnection();aboutToAppear(){// 监听网络状态this.netConn.on(netLost,(){this.isOfflinetrue;});this.netConn.on(netAvailable,(){if(this.isOffline){this.isOfflinefalse;// 网络恢复自动重新加载数据this.retryLoadData();}});this.netConn.register(true);}aboutToDisappear(){this.netConn.unregister();}asyncretryLoadData(){// 重新请求当前页面数据console.info(网络恢复自动重试);}build(){Stack(){// 正常内容Column(){Text(页面主内容).fontSize(20)}.visibility(this.isOffline?Visibility.Hidden:Visibility.Visible)// 断网兜底页Column(){Image($r(app.media.no_network)).width(120).height(120)Text(网络连接已断开).fontSize(18).margin({top:16})Button(点击重试).margin({top:24}).onClick((){this.retryLoadData();})}.width(100%).height(100%).justifyContent(FlexAlign.Center).backgroundColor(#f5f5f5).visibility(this.isOffline?Visibility.Visible:Visibility.Visible)}.width(100%).height(100%)}}兜底页面的几个关键点要有重试按钮用户点一下就能手动刷新不用退出页面重进网络恢复自动重试不用用户手动点体验更好不要用弹窗直接替换整个页面内容层级更清晰除了页面兜底接口请求层面也要做断网处理。请求前先判断当前有没有网络没网就直接走本地缓存或者返回错误不用等接口超时省时间。05 完整网络管理工具类封装把上面的逻辑封装成一个统一的网络管理类项目里直接调用不用每个页面都写一遍监听逻辑。import{connection}fromkit.NetworkKit;import{wifiManager}fromkit.ConnectivityKit;typeNetworkChangeListener(isOnline:boolean,type:string)void;classNetworkManager{privatestaticinstance:NetworkManager;privatenetConn:connection.NetConnection;privatelisteners:NetworkChangeListener[][];privateisOnline:booleantrue;privatenetworkType:stringunknown;privateconstructor(){this.netConnconnection.createNetConnection();this.initListener();}staticgetInstance():NetworkManager{if(!NetworkManager.instance){NetworkManager.instancenewNetworkManager();}returnNetworkManager.instance;}privateinitListener(){this.netConn.on(netAvailable,(data){this.isOnlinetrue;this.networkTypedata.bearerTypes.includes(connection.NetBearType.BEARER_WIFI)?wifi:cellular;this.notifyListeners();});this.netConn.on(netLost,(){this.isOnlinefalse;this.networkTypenone;this.notifyListeners();});this.netConn.register(true);}// 页面注册监听addListener(listener:NetworkChangeListener){this.listeners.push(listener);// 注册时立刻返回当前状态listener(this.isOnline,this.networkType);}// 页面销毁时移除监听防止内存泄漏removeListener(listener:NetworkChangeListener){this.listenersthis.listeners.filter(ll!listener);}privatenotifyListeners(){this.listeners.forEach(ll(this.isOnline,this.networkType));}// 主动判断是否联网isNetworkAvailable():boolean{returnthis.isOnline;}// 判断是否是WiFiisWifi():boolean{returnthis.networkTypewifi;}// 获取WiFi信号强度asyncgetWifiRssi():Promisenumber{constwifiwifiManager.getWifiInstance();if(!wifi.isWifiActive())return-100;returnwifi.getLinkedInfo().rssi;}}// 使用方式constnetMgrNetworkManager.getInstance();// 页面里注册监听netMgr.addListener((isOnline,type){console.info(网络状态:,isOnline,type);});这样封装之后任何页面只需要addListener就能收到网络变化通知页面销毁时removeListener就行。不用每个页面都去创建netConnection也不会出现重复注册的问题。