HarmonyOS APP开发中网络状态监听:在线/离线检测
HarmonyOS APP开发中网络状态监听:在线/离线检测
让你的应用拥有网络感知能力,优雅应对各种网络环境
一、为什么需要网络状态监听?
用户打开你的应用,发现数据加载不出来,是网络问题还是服务器问题?用户切换了WiFi和4G,应用是否需要重新请求?用户走进电梯信号丢失,应用如何优雅降级?
这些问题的答案都指向同一个需求:网络状态监听。应用需要实时感知网络环境的变化,并做出相应的响应。
网络状态监听要解决的核心问题:
用户体验优化:网络断开时,不要让用户盯着加载圈发呆,而是给出明确提示。网络恢复时,自动重试未完成的请求。
智能请求策略:WiFi环境下可以下载大文件,移动网络下提示用户注意流量。弱网环境下降低请求频率或请求小图。
资源管理:网络不可用时暂停实时推送、停止轮询,节省电量和流量。
故障排查:记录网络状态变化日志,帮助定位用户反馈的问题。
鸿蒙系统提供了@ohos.net.connection模块,可以全面监听网络状态变化。
二、核心原理:网络状态监听机制
2.1 网络状态监听流程
2.2 网络类型与连接状态
| 网络类型 | 说明 | 典型场景 |
|---|---|---|
| WIFI | WiFi连接 | 家庭、办公室 |
| CELLULAR | 蜂窝网络 | 4G/5G移动网络 |
| ETHERNET | 以太网 | 有线连接设备 |
| BLUETOOTH | 蓝牙网络 | 蓝牙共享网络 |
| VPN | VPN连接 | 安全访问内网 |
| 连接状态 | 说明 |
|---|---|
| UNKNOWN | 未知状态 |
| CONNECTED | 已连接 |
| DISCONNECTED | 已断开 |
| CONNECTING | 连接中 |
| DISCONNECTING | 断开中 |
2.3 鸿蒙网络连接API
import connection from '@ohos.net.connection';
// 创建网络连接监听器
let netConnection = connection.createNetConnection();
// 注册监听
netConnection.on('netAvailable', (data) => {
console.info('网络可用:', data.netHandle.netId);
});
netConnection.on('netLost', (data) => {
console.info('网络丢失:', data.netHandle.netId);
});
// 获取当前网络状态
let netHandle = await connection.getDefaultNet();
let capabilities = await connection.getNetCapabilities(netHandle);
三、代码实战:三种典型场景
场景一:基础网络状态监听
实现完整的网络状态监听,包括在线/离线检测、网络类型识别。
import connection from '@ohos.net.connection';
import { BusinessError } from '@ohos.base';
// 网络状态信息
interface NetworkStatus {
isConnected: boolean; // 是否连接
networkType: NetworkType; // 网络类型
isMetered: boolean; // 是否计费网络
signalStrength: number; // 信号强度(0-100)
ssid?: string; // WiFi名称
lastUpdate: number; // 最后更新时间
}
// 网络类型枚举
enum NetworkType {
UNKNOWN = 'unknown',
WIFI = 'wifi',
CELLULAR_4G = '4g',
CELLULAR_5G = '5g',
ETHERNET = 'ethernet',
BLUETOOTH = 'bluetooth',
VPN = 'vpn'
}
// 网络状态管理器
class NetworkStatusManager {
private netConnection: connection.NetConnection | null = null;
private currentStatus: NetworkStatus;
// 回调
private onStatusChange: ((status: NetworkStatus) => void) | null = null;
private onOnline: (() => void) | null = null;
private onOffline: (() => void) | null = null;
constructor() {
// 初始化状态
this.currentStatus = {
isConnected: false,
networkType: NetworkType.UNKNOWN,
isMetered: true,
signalStrength: 0,
lastUpdate: Date.now()
};
}
// 启动监听
async start(): Promise<void> {
// 创建网络连接监听器
this.netConnection = connection.createNetConnection();
// 注册监听事件
this.setupListeners();
// 获取初始状态
await this.updateCurrentStatus();
console.info('网络状态监听已启动');
}
// 设置监听
private setupListeners(): void {
if (!this.netConnection) return;
// 网络可用
this.netConnection.on('netAvailable', async (data: connection.NetHandle) => {
console.info('网络可用:', data.netId);
await this.updateCurrentStatus();
// 触发上线回调
if (!this.currentStatus.isConnected) {
this.currentStatus.isConnected = true;
this.onOnline?.();
}
this.notifyStatusChange();
});
// 网络丢失
this.netConnection.on('netLost', (data: connection.NetHandle) => {
console.info('网络丢失:', data.netId);
this.currentStatus = {
isConnected: false,
networkType: NetworkType.UNKNOWN,
isMetered: true,
signalStrength: 0,
lastUpdate: Date.now()
};
this.onOffline?.();
this.notifyStatusChange();
});
// 网络变更(切换网络)
this.netConnection.on('netChange', async (data: connection.NetHandle) => {
console.info('网络变更:', data.netId);
await this.updateCurrentStatus();
this.notifyStatusChange();
});
// 连接属性变化
this.netConnection.on('netConnectionPropertiesChanged', async (data: connection.ConnectionProperties) => {
console.info('连接属性变化');
await this.updateCurrentStatus();
this.notifyStatusChange();
});
// 网络能力变化
this.netConnection.on('netCapabilitiesChange', async (data: connection.NetCapabilityInfo) => {
console.info('网络能力变化');
await this.updateCurrentStatus();
this.notifyStatusChange();
});
}
// 更新当前状态
private async updateCurrentStatus(): Promise<void> {
try {
// 获取默认网络
let netHandle = await connection.getDefaultNet();
if (!netHandle || netHandle.netId === 0) {
// 无网络连接
this.currentStatus.isConnected = false;
this.currentStatus.networkType = NetworkType.UNKNOWN;
this.currentStatus.lastUpdate = Date.now();
return;
}
// 获取网络能力
let capabilities = await connection.getNetCapabilities(netHandle);
// 解析网络类型
let networkType = this.parseNetworkType(capabilities);
// 判断是否计费网络
let isMetered = this.checkIfMetered(capabilities);
// 获取信号强度(如果支持)
let signalStrength = await this.getSignalStrength();
// 获取WiFi SSID(如果是WiFi)
let ssid: string | undefined;
if (networkType === NetworkType.WIFI) {
ssid = await this.getWifiSsid();
}
this.currentStatus = {
isConnected: true,
networkType: networkType,
isMetered: isMetered,
signalStrength: signalStrength,
ssid: ssid,
lastUpdate: Date.now()
};
} catch (error) {
console.error('更新网络状态失败:', error);
// 出错时假设无网络
this.currentStatus.isConnected = false;
this.currentStatus.lastUpdate = Date.now();
}
}
// 解析网络类型
private parseNetworkType(capabilities: connection.NetCapabilities): NetworkType {
// 检查是否是WiFi
if (capabilities.bearerTypes.includes(connection.BearerType.BEARER_WIFI)) {
return NetworkType.WIFI;
}
// 检查是否是蜂窝网络
if (capabilities.bearerTypes.includes(connection.BearerType.BEARER_CELLULAR)) {
// 进一步判断是4G还是5G
// 简化处理,返回4G
return NetworkType.CELLULAR_4G;
}
// 检查是否是以太网
if (capabilities.bearerTypes.includes(connection.BearerType.BEARER_ETHERNET)) {
return NetworkType.ETHERNET;
}
// 检查是否是蓝牙
if (capabilities.bearerTypes.includes(connection.BearerType.BEARER_BLUETOOTH)) {
return NetworkType.BLUETOOTH;
}
return NetworkType.UNKNOWN;
}
// 判断是否计费网络
private checkIfMetered(capabilities: connection.NetCapabilities): boolean {
// WiFi和以太网通常不计费
if (capabilities.bearerTypes.includes(connection.BearerType.BEARER_WIFI) ||
capabilities.bearerTypes.includes(connection.BearerType.BEARER_ETHERNET)) {
return false;
}
// 蜂窝网络计费
return true;
}
// 获取信号强度
private async getSignalStrength(): Promise<number> {
// 简化处理,返回固定值
// 实际需要调用系统API获取
return 80;
}
// 获取WiFi SSID
private async getWifiSsid(): Promise<string | undefined> {
// 简化处理
// 实际需要调用WiFi API获取
return 'MyWiFi';
}
// 通知状态变化
private notifyStatusChange(): void {
console.info('网络状态更新:', JSON.stringify(this.currentStatus));
this.onStatusChange?.(this.currentStatus);
}
// 停止监听
stop(): void {
if (this.netConnection) {
// 取消所有监听
this.netConnection.off('netAvailable');
this.netConnection.off('netLost');
this.netConnection.off('netChange');
this.netConnection.off('netConnectionPropertiesChanged');
this.netConnection.off('netCapabilitiesChange');
this.netConnection = null;
}
console.info('网络状态监听已停止');
}
// 获取当前状态
getCurrentStatus(): NetworkStatus {
return { ...this.currentStatus };
}
// 判断是否在线
isOnline(): boolean {
return this.currentStatus.isConnected;
}
// 判断是否是WiFi
isWifi(): boolean {
return this.currentStatus.networkType === NetworkType.WIFI;
}
// 判断是否是移动网络
isMobile(): boolean {
return this.currentStatus.networkType === NetworkType.CELLULAR_4G ||
this.currentStatus.networkType === NetworkType.CELLULAR_5G;
}
// 设置回调
setOnStatusChange(callback: (status: NetworkStatus) => void): void {
this.onStatusChange = callback;
}
setOnOnline(callback: () => void): void {
this.onOnline = callback;
}
setOnOffline(callback: () => void): void {
this.onOffline = callback;
}
}
// 网络状态显示组件
@Entry
@Component
struct NetworkStatusPage {
@State networkStatus: NetworkStatus | null = null;
@State statusHistory: string[] = [];
private networkManager: NetworkStatusManager = new NetworkStatusManager();
async aboutToAppear() {
// 设置回调
this.networkManager.setOnStatusChange((status) => {
this.networkStatus = status;
this.addHistory(`状态更新: ${status.isConnected ? '在线' : '离线'} (${status.networkType})`);
});
this.networkManager.setOnOnline(() => {
this.addHistory('网络已连接');
});
this.networkManager.setOnOffline(() => {
this.addHistory('网络已断开');
});
// 启动监听
await this.networkManager.start();
// 获取初始状态
this.networkStatus = this.networkManager.getCurrentStatus();
}
aboutToDisappear() {
this.networkManager.stop();
}
private addHistory(message: string) {
let time = new Date().toLocaleTimeString();
this.statusHistory.unshift(`[${time}] ${message}`);
if (this.statusHistory.length > 20) {
this.statusHistory.pop();
}
}
build() {
Column() {
// 网络状态卡片
if (this.networkStatus) {
this.StatusCard()
}
// 状态历史
Column() {
Text('状态变化历史:')
.fontSize(14)
.width('100%')
List() {
ForEach(this.statusHistory, (log: string, index: number) => {
ListItem() {
Text(log)
.fontSize(12)
.fontFamily('monospace')
}
})
}
.width('100%')
.layoutWeight(1)
.backgroundColor('#F5F5F5')
.padding(10)
}
.width('100%')
.padding(10)
.layoutWeight(1)
}
.width('100%')
.height('100%')
}
@Builder
StatusCard() {
Column() {
// 连接状态
Row() {
Circle()
.width(20)
.height(20)
.fill(this.networkStatus?.isConnected ? '#7ED321' : '#D0021B')
Text(this.networkStatus?.isConnected ? '已连接' : '未连接')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ left: 10 })
}
.width('100%')
Divider().margin({ top: 15, bottom: 15 })
// 网络类型
Row() {
Text('网络类型:')
.fontSize(14)
.layoutWeight(1)
Text(this.getNetworkTypeText())
.fontSize(14)
.fontColor('#4A90E2')
}
.width('100%')
// 是否计费
Row() {
Text('计费网络:')
.fontSize(14)
.layoutWeight(1)
Text(this.networkStatus?.isMetered ? '是' : '否')
.fontSize(14)
.fontColor(this.networkStatus?.isMetered ? '#F5A623' : '#7ED321')
}
.width('100%')
.margin({ top: 10 })
// 信号强度
if (this.networkStatus?.isConnected) {
Row() {
Text('信号强度:')
.fontSize(14)
.layoutWeight(1)
Row() {
Stack() {
Row()
.width(100)
.height(10)
.backgroundColor('#E8E8E8')
.borderRadius(5)
Row()
.width(`${this.networkStatus?.signalStrength}%`)
.height(10)
.backgroundColor('#4A90E2')
.borderRadius(5)
}
.width(100)
.height(10)
Text(`${this.networkStatus?.signalStrength}%`)
.fontSize(12)
.margin({ left: 10 })
}
}
.width('100%')
.margin({ top: 10 })
}
// WiFi SSID
if (this.networkStatus?.ssid) {
Row() {
Text('WiFi名称:')
.fontSize(14)
.layoutWeight(1)
Text(this.networkStatus?.ssid)
.fontSize(14)
.fontColor('#666')
}
.width('100%')
.margin({ top: 10 })
}
}
.width('100%')
.padding(20)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.margin(10)
}
private getNetworkTypeText(): string {
switch (this.networkStatus?.networkType) {
case NetworkType.WIFI:
return 'WiFi';
case NetworkType.CELLULAR_4G:
return '4G';
case NetworkType.CELLULAR_5G:
return '5G';
case NetworkType.ETHERNET:
return '以太网';
case NetworkType.BLUETOOTH:
return '蓝牙';
default:
return '未知';
}
}
}
场景二:智能请求策略
根据网络状态自动调整请求策略。
import connection from '@ohos.net.connection';
// 请求策略配置
interface RequestStrategy {
maxImageSize: number; // 最大图片尺寸
requestTimeout: number; // 请求超时
retryCount: number; // 重试次数
retryDelay: number; // 重试延迟
enablePreload: boolean; // 是否预加载
enableBackgroundSync: boolean; // 是否后台同步
}
// 默认策略
const STRATEGIES = {
// WiFi策略:无限制
WIFI: {
maxImageSize: 4096,
requestTimeout: 30000,
retryCount: 3,
retryDelay: 1000,
enablePreload: true,
enableBackgroundSync: true
} as RequestStrategy,
// 4G策略:适度限制
CELLULAR_4G: {
maxImageSize: 2048,
requestTimeout: 20000,
retryCount: 2,
retryDelay: 2000,
enablePreload: false,
enableBackgroundSync: false
} as RequestStrategy,
// 5G策略:接近WiFi
CELLULAR_5G: {
maxImageSize: 3072,
requestTimeout: 25000,
retryCount: 3,
retryDelay: 1500,
enablePreload: true,
enableBackgroundSync: false
} as RequestStrategy,
// 离线策略
OFFLINE: {
maxImageSize: 0,
requestTimeout: 0,
retryCount: 0,
retryDelay: 0,
enablePreload: false,
enableBackgroundSync: false
} as RequestStrategy
};
// 智能网络请求管理器
class SmartNetworkManager {
private networkManager: NetworkStatusManager;
private currentStrategy: RequestStrategy;
private pendingRequests: Array<() => Promise<void>> = [];
// 回调
private onStrategyChange: ((strategy: RequestStrategy) => void) | null = null;
constructor(networkManager: NetworkStatusManager) {
this.networkManager = networkManager;
this.currentStrategy = STRATEGIES.OFFLINE;
// 监听网络状态变化
this.networkManager.setOnStatusChange((status) => {
this.updateStrategy(status);
});
}
// 更新策略
private updateStrategy(status: NetworkStatus): void {
let newStrategy: RequestStrategy;
if (!status.isConnected) {
newStrategy = STRATEGIES.OFFLINE;
} else {
switch (status.networkType) {
case NetworkType.WIFI:
newStrategy = STRATEGIES.WIFI;
break;
case NetworkType.CELLULAR_4G:
newStrategy = STRATEGIES.CELLULAR_4G;
break;
case NetworkType.CELLULAR_5G:
newStrategy = STRATEGIES.CELLULAR_5G;
break;
default:
newStrategy = STRATEGIES.CELLULAR_4G; // 保守策略
}
}
// 检查策略是否变化
if (JSON.stringify(newStrategy) !== JSON.stringify(this.currentStrategy)) {
this.currentStrategy = newStrategy;
console.info('请求策略已更新:', JSON.stringify(newStrategy));
this.onStrategyChange?.(newStrategy);
// 网络恢复时,执行待处理请求
if (status.isConnected && this.pendingRequests.length > 0) {
this.executePendingRequests();
}
}
}
// 执行待处理请求
private async executePendingRequests(): Promise<void> {
console.info(`执行 ${this.pendingRequests.length} 个待处理请求`);
let requests = [...this.pendingRequests];
this.pendingRequests = [];
for (let request of requests) {
try {
await request();
} catch (error) {
console.error('待处理请求执行失败:', error);
}
}
}
// 执行请求(智能策略)
async executeRequest<T>(
request: () => Promise<T>,
options: {
offlineBehavior?: 'reject' | 'queue' | 'cache'; // 离线行为
requireWifi?: boolean; // 是否要求WiFi
} = {}
): Promise<T | null> {
let status = this.networkManager.getCurrentStatus();
// 检查网络
if (!status.isConnected) {
switch (options.offlineBehavior || 'reject') {
case 'reject':
throw new Error('网络不可用');
case 'queue':
// 加入待处理队列
return new Promise((resolve) => {
this.pendingRequests.push(async () => {
let result = await request();
resolve(result);
});
});
case 'cache':
// 返回缓存数据
return null;
}
}
// 检查WiFi要求
if (options.requireWifi && status.networkType !== NetworkType.WIFI) {
throw new Error('此操作需要WiFi网络');
}
// 执行请求(带重试)
let retryCount = this.currentStrategy.retryCount;
let lastError: Error | null = null;
for (let i = 0; i <= retryCount; i++) {
try {
return await request();
} catch (error) {
lastError = error as Error;
if (i < retryCount) {
// 等待重试
await this.delay(this.currentStrategy.retryDelay * (i + 1));
}
}
}
throw lastError;
}
// 获取图片URL(根据网络调整尺寸)
getImageUrl(originalUrl: string): string {
let maxSize = this.currentStrategy.maxImageSize;
if (maxSize === 0) {
// 离线,返回占位图
return 'asset:///placeholder.png';
}
// 根据最大尺寸调整URL
// 假设图片服务支持尺寸参数
return `${originalUrl}?size=${maxSize}`;
}
// 判断是否可以预加载
canPreload(): boolean {
return this.currentStrategy.enablePreload;
}
// 判断是否可以后台同步
canBackgroundSync(): boolean {
return this.currentStrategy.enableBackgroundSync;
}
// 获取当前策略
getCurrentStrategy(): RequestStrategy {
return { ...this.currentStrategy };
}
// 设置回调
setOnStrategyChange(callback: (strategy: RequestStrategy) => void): void {
this.onStrategyChange = callback;
}
// 延迟工具
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// 使用示例
@Entry
@Component
struct SmartRequestPage {
@State strategyInfo: string = '';
@State networkStatus: NetworkStatus | null = null;
private networkManager: NetworkStatusManager = new NetworkStatusManager();
private smartManager: SmartNetworkManager | null = null;
async aboutToAppear() {
await this.networkManager.start();
this.smartManager = new SmartNetworkManager(this.networkManager);
this.smartManager.setOnStrategyChange((strategy) => {
this.strategyInfo = JSON.stringify(strategy, null, 2);
});
this.networkManager.setOnStatusChange((status) => {
this.networkStatus = status;
});
this.networkStatus = this.networkManager.getCurrentStatus();
this.strategyInfo = JSON.stringify(this.smartManager.getCurrentStrategy(), null, 2);
}
aboutToDisappear() {
this.networkManager.stop();
}
// 测试请求
async testRequest() {
try {
let result = await this.smartManager?.executeRequest(
async () => {
// 模拟请求
await new Promise(resolve => setTimeout(resolve, 1000));
return { data: 'success' };
},
{ offlineBehavior: 'queue' }
);
console.info('请求成功:', result);
} catch (error) {
console.error('请求失败:', error);
}
}
build() {
Column() {
// 网络状态
Row() {
Text('网络状态:')
.fontSize(16)
Text(this.networkStatus?.isConnected ? '在线' : '离线')
.fontSize(16)
.fontColor(this.networkStatus?.isConnected ? '#7ED321' : '#D0021B')
.margin({ left: 10 })
}
.width('100%')
.padding(15)
// 当前策略
Column() {
Text('当前请求策略:')
.fontSize(14)
.width('100%')
Text(this.strategyInfo)
.fontSize(12)
.fontFamily('monospace')
}
.width('100%')
.padding(10)
.backgroundColor('#F5F5F5')
// 测试按钮
Button('测试请求')
.width('100%')
.margin({ top: 20 })
.onClick(() => this.testRequest())
}
.width('100%')
.padding(20)
}
}
场景三:离线缓存与同步
实现离线数据缓存和网络恢复后自动同步。
import connection from '@ohos.net.connection';
import preferences from '@ohos.data.preferences';
// 离线数据项
interface OfflineDataItem {
id: string;
type: string;
data: any;
timestamp: number;
synced: boolean;
}
// 离线数据管理器
class OfflineDataManager {
private storage: preferences.Preferences | null = null;
private pendingSync: OfflineDataItem[] = [];
private networkManager: NetworkStatusManager;
private isSyncing: boolean = false;
// 回调
private onSyncStart: (() => void) | null = null;
private onSyncComplete: ((count: number) => void) | null = null;
private onSyncError: ((error: Error) => void) | null = null;
constructor(networkManager: NetworkStatusManager) {
this.networkManager = networkManager;
// 监听网络恢复
this.networkManager.setOnOnline(() => {
this.syncPendingData();
});
}
// 初始化
async init(context: Context): Promise<void> {
this.storage = await preferences.getPreferences(context, 'offline_data');
// 加载待同步数据
await this.loadPendingData();
}
// 加载待同步数据
private async loadPendingData(): Promise<void> {
if (!this.storage) return;
try {
let dataStr = await this.storage.get('pending_sync', '[]') as string;
this.pendingSync = JSON.parse(dataStr);
console.info(`加载 ${this.pendingSync.length} 条待同步数据`);
} catch (error) {
this.pendingSync = [];
}
}
// 保存待同步数据
private async savePendingData(): Promise<void> {
if (!this.storage) return;
await this.storage.put('pending_sync', JSON.stringify(this.pendingSync));
await this.storage.flush();
}
// 保存数据(离线可用)
async saveData(type: string, data: any): Promise<string> {
let item: OfflineDataItem = {
id: `offline_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
type: type,
data: data,
timestamp: Date.now(),
synced: false
};
// 检查网络状态
if (this.networkManager.isOnline()) {
// 在线,直接同步
try {
await this.syncItem(item);
item.synced = true;
console.info('数据已同步:', item.id);
} catch (error) {
// 同步失败,加入待同步队列
this.pendingSync.push(item);
await this.savePendingData();
console.warn('同步失败,已加入待同步队列:', item.id);
}
} else {
// 离线,加入待同步队列
this.pendingSync.push(item);
await this.savePendingData();
console.info('离线保存,已加入待同步队列:', item.id);
}
return item.id;
}
// 同步单个数据项
private async syncItem(item: OfflineDataItem): Promise<void> {
// 根据类型调用不同的同步API
switch (item.type) {
case 'user_profile':
// await api.updateUserProfile(item.data);
break;
case 'order':
// await api.createOrder(item.data);
break;
case 'message':
// await api.sendMessage(item.data);
break;
default:
throw new Error(`未知数据类型: ${item.type}`);
}
}
// 同步待处理数据
async syncPendingData(): Promise<void> {
if (this.isSyncing) {
console.warn('同步进行中,跳过');
return;
}
if (this.pendingSync.length === 0) {
return;
}
if (!this.networkManager.isOnline()) {
console.warn('网络不可用,跳过同步');
return;
}
this.isSyncing = true;
this.onSyncStart?.();
console.info(`开始同步 ${this.pendingSync.length} 条数据`);
let successCount = 0;
let failedItems: OfflineDataItem[] = [];
for (let item of this.pendingSync) {
try {
await this.syncItem(item);
successCount++;
console.info(`同步成功: ${item.id}`);
} catch (error) {
console.error(`同步失败: ${item.id}`, error);
failedItems.push(item);
}
}
// 更新待同步列表
this.pendingSync = failedItems;
await this.savePendingData();
this.isSyncing = false;
if (successCount > 0) {
this.onSyncComplete?.(successCount);
}
if (failedItems.length > 0) {
this.onSyncError?.(new Error(`${failedItems.length} 条数据同步失败`));
}
}
// 获取待同步数量
getPendingCount(): number {
return this.pendingSync.length;
}
// 清除所有待同步数据
async clearAll(): Promise<void> {
this.pendingSync = [];
await this.savePendingData();
}
// 设置回调
setOnSyncStart(callback: () => void): void {
this.onSyncStart = callback;
}
setOnSyncComplete(callback: (count: number) => void): void {
this.onSyncComplete = callback;
}
setOnSyncError(callback: (error: Error) => void): void {
this.onSyncError = callback;
}
}
// 离线数据管理页面
@Entry
@Component
struct OfflineDataPage {
@State pendingCount: number = 0;
@State syncStatus: string = '';
@State logs: string[] = [];
private networkManager: NetworkStatusManager = new NetworkStatusManager();
private offlineManager: OfflineDataManager | null = null;
async aboutToAppear() {
await this.networkManager.start();
this.offlineManager = new OfflineDataManager(this.networkManager);
// await this.offlineManager.init(getContext(this));
this.offlineManager.setOnSyncStart(() => {
this.syncStatus = '同步中...';
this.addLog('开始同步数据');
});
this.offlineManager.setOnSyncComplete((count) => {
this.syncStatus = '';
this.addLog(`同步完成: ${count} 条`);
this.pendingCount = this.offlineManager?.getPendingCount() || 0;
});
this.offlineManager.setOnSyncError((error) => {
this.syncStatus = '';
this.addLog(`同步错误: ${error.message}`);
});
this.pendingCount = this.offlineManager.getPendingCount();
}
aboutToDisappear() {
this.networkManager.stop();
}
// 保存测试数据
async saveTestData() {
let id = await this.offlineManager?.saveData('test', {
value: Math.random(),
timestamp: Date.now()
});
this.pendingCount = this.offlineManager?.getPendingCount() || 0;
this.addLog(`保存数据: ${id}`);
}
// 手动同步
async manualSync() {
await this.offlineManager?.syncPendingData();
}
private addLog(message: string) {
let time = new Date().toLocaleTimeString();
this.logs.unshift(`[${time}] ${message}`);
if (this.logs.length > 20) {
this.logs.pop();
}
}
build() {
Column() {
// 状态显示
Row() {
Text(`待同步: ${this.pendingCount} 条`)
.fontSize(16)
if (this.syncStatus) {
Text(this.syncStatus)
.fontSize(14)
.fontColor('#F5A623')
.margin({ left: 20 })
}
}
.width('100%')
.padding(15)
// 操作按钮
Row() {
Button('保存测试数据')
.onClick(() => this.saveTestData())
.layoutWeight(1)
Button('手动同步')
.onClick(() => this.manualSync())
.layoutWeight(1)
.margin({ left: 10 })
}
.width('100%')
.padding(10)
// 日志
List() {
ForEach(this.logs, (log: string, index: number) => {
ListItem() {
Text(log)
.fontSize(12)
.fontFamily('monospace')
}
})
}
.width('100%')
.layoutWeight(1)
.backgroundColor('#F5F5F5')
.padding(10)
}
.width('100%')
.height('100%')
}
}
四、踩坑与注意事项
坑点一:监听未取消
页面销毁时忘记取消监听,导致内存泄漏。
// ❌ 错误:忘记取消监听
aboutToDisappear() {
// 没有取消监听!
}
// ✅ 正确:取消所有监听
aboutToDisappear() {
if (this.netConnection) {
this.netConnection.off('netAvailable');
this.netConnection.off('netLost');
this.netConnection.off('netChange');
this.netConnection = null;
}
}
坑点二:状态判断时机错误
在监听回调中直接判断状态,可能不准确。
// ❌ 错误:在回调中直接判断
this.netConnection.on('netAvailable', () => {
// 此时网络可能已经又断了
this.fetchData(); // 可能失败
});
// ✅ 正确:在回调中重新获取状态
this.netConnection.on('netAvailable', async () => {
let status = await this.getCurrentNetworkStatus();
if (status.isConnected) {
this.fetchData();
}
});
坑点三:频繁触发处理
网络状态可能频繁变化,需要防抖处理。
// 带防抖的状态处理
class DebouncedNetworkHandler {
private debounceTimer: number = -1;
private debounceDelay: number = 1000;
handleNetworkChange(callback: () => void): void {
// 清除之前的定时器
if (this.debounceTimer !== -1) {
clearTimeout(this.debounceTimer);
}
// 设置新的定时器
this.debounceTimer = setTimeout(() => {
callback();
this.debounceTimer = -1;
}, this.debounceDelay);
}
}
五、HarmonyOS 6适配指南
5.1 增强的网络能力检测
HarmonyOS 6提供了更详细的网络能力信息。
import connection from '@ohos.net.connection';
// HarmonyOS 6: 获取详细网络能力
let netHandle = await connection.getDefaultNet();
let capabilities = await connection.getNetCapabilities(netHandle);
// 网络能力检查
let hasInternet = capabilities.networkCap.includes(connection.NetCap.NET_CAPABILITY_INTERNET);
let hasMms = capabilities.networkCap.includes(connection.NetCap.NET_CAPABILITY_MMS);
let hasInternal = capabilities.networkCap.includes(connection.NetCap.NET_CAPABILITY_INTERNAL_DEFAULT);
// 链路下行带宽
let downlinkKbps = capabilities.linkDownBandwidthKbps;
// 链路上行带宽
let uplinkKbps = capabilities.linkUpBandwidthKbps;
5.2 网络质量评估
HarmonyOS 6支持网络质量评估API。
// HarmonyOS 6: 网络质量评估
let qualityInfo = await connection.getNetworkQuality();
console.info('网络质量评分:', qualityInfo.score);
console.info('时延:', qualityInfo.delay);
console.info('抖动:', qualityInfo.jitter);
console.info('丢包率:', qualityInfo.packetLoss);
六、总结一下下
网络状态监听是现代应用的必备能力。本文从三个场景展开:
基础监听:监听网络连接、断开、切换等事件,获取网络类型、计费状态、信号强度等信息。这是所有网络智能功能的基础。
智能请求策略:根据网络状态自动调整请求参数,如图片尺寸、超时时间、重试策略等。WiFi下无限制,移动网络下适度限制,离线时优雅降级。
离线缓存同步:离线时将数据保存到本地,网络恢复后自动同步。这是提升用户体验的关键,让应用在网络不佳时也能正常使用。
三个常见坑点:监听未取消、状态判断时机错误、频繁触发处理。遇到网络状态问题时,先排查这三个方面。
HarmonyOS 6带来了更详细的网络能力检测和网络质量评估API,让应用能更精准地感知网络环境,做出最优决策。
下一篇文章,我们将深入网络质量评估,实现带宽与延迟检测!
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)