uni.onnetworkstatuschange 无法用于启动检测,因其仅在网络切换时触发,冷启动时不回调;必须用 uni.getnetworktype 在 onlaunch 和 onshow 中双时机快照初始化,并处理权限与超时兜底。

App 启动时无法仅靠 uni.onNetworkStatusChange 捕获初始网络状态,必须用 uni.getNetworkType 做快照初始化,否则冷启动页面会显示“未知”或白屏等待。
为什么 onNetworkStatusChange 不能用于启动检测
uni.onNetworkStatusChange 是被动监听 API,只在网络栈真实切换时触发,App 首次启动时它不会自动回调。iOS 真机甚至在 kill 后重启也不发首次通知;Android 冷启动时部分机型网络栈未就绪,onNetworkStatusChange 根本不注册成功。它不是轮询,也不是初始化工具。
常见错误现象:
– 页面 onLoad 里直接依赖 isConnected 渲染按钮,结果始终灰显
– uni.getNetworkType 放在页面里调用,安卓返回 'unknown',iOS 卡住 2 秒才回调,UI 阻塞
- 必须把初始化逻辑提前到
App.vue的onLaunch和onShow中执行 - 不要在页面组件或
main.js的created里单独调用uni.getNetworkType—— 生命周期不可控,容易漏掉 - 失败回调里别静默吞错,至少
console.error('getNetworkType fail', err),否则上线后无法定位是权限还是系统忙
onLaunch + onShow 双时机调用 getNetworkType
单次调用不可靠,需组合两个生命周期确保覆盖所有启动路径:冷启动、热启动、从后台切回前台。
实操建议:
– onLaunch 中调一次,作为全局初始值(比如挂到 Vue.prototype.$network 或 Pinia store)
– onShow 中再调一次,覆盖从后台切回前台的场景(此时 onNetworkStatusChange 才重新注册)
– 两次都加 800ms 超时 fallback,避免阻塞 UI(尤其 iOS 无网时可能卡住)
- 超时后统一设为
{ isConnected: false, networkType: 'unknown' },比留空更利于 UI 渲染兜底态 - 返回
networkType: 'none'不等于断网,可能是飞行模式或系统级禁用,需结合用户操作上下文判断 - 安卓部分机型在
onLaunch时仍返回'unknown',这是正常行为,不是 bug,必须靠onShow补救
如何把初始状态同步给所有页面
不能每个页面都手动调 uni.getNetworkType,会造成重复请求和状态不一致。推荐用响应式数据流驱动。
典型做法:
– 在 App.vue 的 data 或 store 中定义 networkStatus: { isConnected: false, networkType: 'unknown' }
– onLaunch 和 onShow 中更新该值
– 所有页面通过 watch 或 computed 订阅它,触发 UI 刷新(如禁用上传按钮、显示离线 banner)
- 别在
watch回调里直接发请求——网络状态变 true 不代表服务可达,要额外 ping 健康接口 - 如果用了 Vue 3 + Composition API,可用
provide/inject把networkStatus注入子组件,避免层层 props 透传 - 注意:H5 端
uni.getNetworkType始终返回'unknown',别在浏览器调试时误判逻辑
权限和平台兼容性必须前置处理
iOS 和 Android 10+ 都要求开启定位权限才能拿到准确 networkType,否则 uni.getNetworkType 返回恒为 'none' 或 'unknown',且 onNetworkStatusChange 的 networkType 字段也失效。
关键动作:
– manifest.json 中补全 iOS 描述字段:NSLocationWhenInUseUsageDescription
– Android 需动态申请 android.permission.ACCESS_FINE_LOCATION(即使你不需要位置,WiFi 类型依赖它)
– 引导文案别写“获取位置”,写“获取网络类型所需权限”
- 用户拒绝定位权限后,
networkType不可用,但isConnected仍可工作(靠系统底层连通性),所以降级策略是:只依赖isConnected做基础判断,放弃networkType分类 - iOS 真机测试前务必检查「设置 → 隐私与安全性 → 定位服务」是否开启,且本 App 权限设为「使用期间」
- 华为/小米等定制 ROM 可能拦截权限弹窗,需在
onLaunch里加uni.showModal提前引导用户手动去设置页开启
最常被忽略的一点:启动时拿到 isConnected: true 和 networkType: 'wifi',只代表设备链路层连上了,不代表你能访问业务服务器。考勤、IoT 控制等场景,必须在状态就绪后主动 uni.request 一个轻量健康接口(如 /health),超时即判定为“假连网”。这个验证步骤不能省,也不能延迟到用户点击按钮时才做。











