239 lines
6.1 KiB
Dart
239 lines
6.1 KiB
Dart
|
|
import 'package:flutter/foundation.dart';
|
|||
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|||
|
|
import 'dart:async';
|
|||
|
|
|
|||
|
|
/// 网络连接状态枚举
|
|||
|
|
enum NetworkStatus {
|
|||
|
|
connected,
|
|||
|
|
disconnected,
|
|||
|
|
unknown,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 网络连接类型枚举
|
|||
|
|
enum NetworkType {
|
|||
|
|
wifi,
|
|||
|
|
mobile,
|
|||
|
|
ethernet,
|
|||
|
|
none,
|
|||
|
|
unknown,
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 网络状态数据模型
|
|||
|
|
class NetworkState {
|
|||
|
|
final NetworkStatus status;
|
|||
|
|
final NetworkType type;
|
|||
|
|
final bool isOnline;
|
|||
|
|
final DateTime lastChecked;
|
|||
|
|
|
|||
|
|
const NetworkState({
|
|||
|
|
required this.status,
|
|||
|
|
required this.type,
|
|||
|
|
required this.isOnline,
|
|||
|
|
required this.lastChecked,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
NetworkState copyWith({
|
|||
|
|
NetworkStatus? status,
|
|||
|
|
NetworkType? type,
|
|||
|
|
bool? isOnline,
|
|||
|
|
DateTime? lastChecked,
|
|||
|
|
}) {
|
|||
|
|
return NetworkState(
|
|||
|
|
status: status ?? this.status,
|
|||
|
|
type: type ?? this.type,
|
|||
|
|
isOnline: isOnline ?? this.isOnline,
|
|||
|
|
lastChecked: lastChecked ?? this.lastChecked,
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
bool operator ==(Object other) {
|
|||
|
|
if (identical(this, other)) return true;
|
|||
|
|
return other is NetworkState &&
|
|||
|
|
other.status == status &&
|
|||
|
|
other.type == type &&
|
|||
|
|
other.isOnline == isOnline;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
int get hashCode {
|
|||
|
|
return status.hashCode ^
|
|||
|
|
type.hashCode ^
|
|||
|
|
isOnline.hashCode;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
String toString() {
|
|||
|
|
return 'NetworkState(status: $status, type: $type, isOnline: $isOnline, lastChecked: $lastChecked)';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 网络状态管理Provider
|
|||
|
|
class NetworkNotifier extends StateNotifier<NetworkState> {
|
|||
|
|
late StreamSubscription<List<ConnectivityResult>> _connectivitySubscription;
|
|||
|
|
final Connectivity _connectivity = Connectivity();
|
|||
|
|
|
|||
|
|
NetworkNotifier()
|
|||
|
|
: super(NetworkState(
|
|||
|
|
status: NetworkStatus.unknown,
|
|||
|
|
type: NetworkType.unknown,
|
|||
|
|
isOnline: false,
|
|||
|
|
lastChecked: DateTime.now(),
|
|||
|
|
)) {
|
|||
|
|
_initializeNetworkMonitoring();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 初始化网络监控
|
|||
|
|
void _initializeNetworkMonitoring() {
|
|||
|
|
// 监听网络连接状态变化
|
|||
|
|
_connectivitySubscription = _connectivity.onConnectivityChanged.listen(
|
|||
|
|
(List<ConnectivityResult> results) {
|
|||
|
|
_updateNetworkState(results);
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 初始检查网络状态
|
|||
|
|
_checkInitialConnectivity();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 检查初始网络连接状态
|
|||
|
|
Future<void> _checkInitialConnectivity() async {
|
|||
|
|
try {
|
|||
|
|
final results = await _connectivity.checkConnectivity();
|
|||
|
|
_updateNetworkState(results);
|
|||
|
|
} catch (e) {
|
|||
|
|
if (kDebugMode) {
|
|||
|
|
print('Error checking initial connectivity: $e');
|
|||
|
|
}
|
|||
|
|
state = state.copyWith(
|
|||
|
|
status: NetworkStatus.unknown,
|
|||
|
|
type: NetworkType.unknown,
|
|||
|
|
isOnline: false,
|
|||
|
|
lastChecked: DateTime.now(),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 更新网络状态
|
|||
|
|
void _updateNetworkState(List<ConnectivityResult> results) {
|
|||
|
|
// 取第一个有效的连接结果,如果列表为空则认为无连接
|
|||
|
|
final result = results.isNotEmpty ? results.first : ConnectivityResult.none;
|
|||
|
|
final networkType = _mapConnectivityResultToNetworkType(result);
|
|||
|
|
final isOnline = result != ConnectivityResult.none;
|
|||
|
|
final status = isOnline ? NetworkStatus.connected : NetworkStatus.disconnected;
|
|||
|
|
|
|||
|
|
state = NetworkState(
|
|||
|
|
status: status,
|
|||
|
|
type: networkType,
|
|||
|
|
isOnline: isOnline,
|
|||
|
|
lastChecked: DateTime.now(),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
if (kDebugMode) {
|
|||
|
|
print('Network state updated: $state');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 将ConnectivityResult映射到NetworkType
|
|||
|
|
NetworkType _mapConnectivityResultToNetworkType(ConnectivityResult result) {
|
|||
|
|
switch (result) {
|
|||
|
|
case ConnectivityResult.wifi:
|
|||
|
|
return NetworkType.wifi;
|
|||
|
|
case ConnectivityResult.mobile:
|
|||
|
|
return NetworkType.mobile;
|
|||
|
|
case ConnectivityResult.ethernet:
|
|||
|
|
return NetworkType.ethernet;
|
|||
|
|
case ConnectivityResult.none:
|
|||
|
|
return NetworkType.none;
|
|||
|
|
default:
|
|||
|
|
return NetworkType.unknown;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 手动刷新网络状态
|
|||
|
|
Future<void> refreshNetworkStatus() async {
|
|||
|
|
try {
|
|||
|
|
final results = await _connectivity.checkConnectivity();
|
|||
|
|
_updateNetworkState(results);
|
|||
|
|
} catch (e) {
|
|||
|
|
if (kDebugMode) {
|
|||
|
|
print('Error refreshing network status: $e');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 检查是否有网络连接
|
|||
|
|
bool get isConnected => state.isOnline;
|
|||
|
|
|
|||
|
|
/// 检查是否为WiFi连接
|
|||
|
|
bool get isWifiConnected => state.type == NetworkType.wifi && state.isOnline;
|
|||
|
|
|
|||
|
|
/// 检查是否为移动网络连接
|
|||
|
|
bool get isMobileConnected => state.type == NetworkType.mobile && state.isOnline;
|
|||
|
|
|
|||
|
|
/// 获取网络类型描述
|
|||
|
|
String get networkTypeDescription {
|
|||
|
|
switch (state.type) {
|
|||
|
|
case NetworkType.wifi:
|
|||
|
|
return 'WiFi';
|
|||
|
|
case NetworkType.mobile:
|
|||
|
|
return '移动网络';
|
|||
|
|
case NetworkType.ethernet:
|
|||
|
|
return '以太网';
|
|||
|
|
case NetworkType.none:
|
|||
|
|
return '无网络';
|
|||
|
|
case NetworkType.unknown:
|
|||
|
|
return '未知网络';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 获取网络状态描述
|
|||
|
|
String get statusDescription {
|
|||
|
|
switch (state.status) {
|
|||
|
|
case NetworkStatus.connected:
|
|||
|
|
return '已连接';
|
|||
|
|
case NetworkStatus.disconnected:
|
|||
|
|
return '已断开';
|
|||
|
|
case NetworkStatus.unknown:
|
|||
|
|
return '未知状态';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@override
|
|||
|
|
void dispose() {
|
|||
|
|
_connectivitySubscription.cancel();
|
|||
|
|
super.dispose();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// 网络状态Provider
|
|||
|
|
final networkProvider = StateNotifierProvider<NetworkNotifier, NetworkState>(
|
|||
|
|
(ref) => NetworkNotifier(),
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/// 网络连接状态Provider(简化版)
|
|||
|
|
final isConnectedProvider = Provider<bool>(
|
|||
|
|
(ref) => ref.watch(networkProvider).isOnline,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/// 网络类型Provider
|
|||
|
|
final networkTypeProvider = Provider<NetworkType>(
|
|||
|
|
(ref) => ref.watch(networkProvider).type,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/// WiFi连接状态Provider
|
|||
|
|
final isWifiConnectedProvider = Provider<bool>(
|
|||
|
|
(ref) {
|
|||
|
|
final networkState = ref.watch(networkProvider);
|
|||
|
|
return networkState.type == NetworkType.wifi && networkState.isOnline;
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
/// 移动网络连接状态Provider
|
|||
|
|
final isMobileConnectedProvider = Provider<bool>(
|
|||
|
|
(ref) {
|
|||
|
|
final networkState = ref.watch(networkProvider);
|
|||
|
|
return networkState.type == NetworkType.mobile && networkState.isOnline;
|
|||
|
|
},
|
|||
|
|
);
|