我有一个网络调用要执行。但在此之前,我需要检查设备是否有互联网连接。
这是我目前为止所做的:
var connectivityResult = new Connectivity().checkConnectivity();// User defined class
if (connectivityResult == ConnectivityResult.mobile ||
connectivityResult == ConnectivityResult.wifi) {*/
this.getData();
} else {
neverSatisfied();
}
上述方法行不通。
我发现仅仅使用连接包不足以判断互联网是否可用。在安卓系统中,它只会检查是否有WIFI或移动数据是否打开,而不会检查是否有实际的互联网连接。在我的测试中,即使没有移动信号ConnectivityResult。Mobile将返回true。
在IOS系统中,我的测试发现,连接插件在手机没有信号的情况下能够正确地检测出是否有网络连接,而Android系统中才存在这个问题。
我找到的解决方案是使用data_connection_checker包以及连接性包。这只是通过向几个可靠的地址发出请求来确保有一个互联网连接,检查的默认超时时间大约是10秒。
我完成的isInternet函数看起来有点像这样:
Future<bool> isInternet() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
// I am connected to a mobile network, make sure there is actually a net connection.
if (await DataConnectionChecker().hasConnection) {
// Mobile data detected & internet connection confirmed.
return true;
} else {
// Mobile data detected but no internet connection found.
return false;
}
} else if (connectivityResult == ConnectivityResult.wifi) {
// I am connected to a WIFI network, make sure there is actually a net connection.
if (await DataConnectionChecker().hasConnection) {
// Wifi detected & internet connection confirmed.
return true;
} else {
// Wifi detected but no internet connection found.
return false;
}
} else {
// Neither mobile data or WIFI detected, not internet connection found.
return false;
}
}
if (await DataConnectionChecker(). hasconnection)部分对于移动连接和wifi连接都是一样的,可能应该移动到一个单独的函数。我在这里没有这样做是为了让它更易于阅读。
我已经创建了一个包,(我认为)可以可靠地处理这个问题。
在pub.dev上的包
这个包在GitHub上
欢迎讨论。你可以使用GitHub上的问题跟踪器。
我不再认为这是一个可靠的方法:
想在@Oren的回答中添加一些东西:你真的应该再添加一个catch,它将捕获所有其他异常(为了安全起见),或者只是完全删除异常类型并使用一个catch,它处理所有异常:
案例1:
try {
await Firestore.instance
.runTransaction((Transaction tx) {})
.timeout(Duration(seconds: 5));
hasConnection = true;
} on PlatformException catch(_) { // May be thrown on Airplane mode
hasConnection = false;
} on TimeoutException catch(_) {
hasConnection = false;
} catch (_) {
hasConnection = false;
}
或者更简单…
案例2:
try {
await Firestore.instance
.runTransaction((Transaction tx) {})
.timeout(Duration(seconds: 5));
hasConnection = true;
} catch (_) {
hasConnection = false;
}
使用connectivity_widget: ^0.1.7
添加附件:
dependencies:
connectivity_widget: ^0.1.7
添加代码:
ConnectivityWidget(
builder: (context, isOnline) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"${isOnline ? 'Connected' : 'Offline'}",
style: TextStyle(
fontSize: 30,
color: isOnline ? Colors.green : Colors.red),
),
],
),
),
)
输出:
我为小部件状态创建了一个基类
使用BaseState<LoginPage>代替State<LoginPage>
然后使用布尔变量isOnline
Text(isOnline ? 'is Online' : 'is Offline')
首先,添加连接性插件:
dependencies:
connectivity: ^0.4.3+2
然后添加BaseState类
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/widgets.dart';
/// a base class for any statful widget for checking internet connectivity
abstract class BaseState<T extends StatefulWidget> extends State {
void castStatefulWidget();
final Connectivity _connectivity = Connectivity();
StreamSubscription<ConnectivityResult> _connectivitySubscription;
/// the internet connectivity status
bool isOnline = true;
/// initialize connectivity checking
/// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initConnectivity() async {
// Platform messages may fail, so we use a try/catch PlatformException.
try {
await _connectivity.checkConnectivity();
} on PlatformException catch (e) {
print(e.toString());
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) {
return;
}
await _updateConnectionStatus().then((bool isConnected) => setState(() {
isOnline = isConnected;
}));
}
@override
void initState() {
super.initState();
initConnectivity();
_connectivitySubscription = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) async {
await _updateConnectionStatus().then((bool isConnected) => setState(() {
isOnline = isConnected;
}));
});
}
@override
void dispose() {
_connectivitySubscription.cancel();
super.dispose();
}
Future<bool> _updateConnectionStatus() async {
bool isConnected;
try {
final List<InternetAddress> result =
await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
isConnected = true;
}
} on SocketException catch (_) {
isConnected = false;
return false;
}
return isConnected;
}
}
您需要像这样在您的状态下强制转换小部件
@override
void castStatefulWidget() {
// ignore: unnecessary_statements
widget is StudentBoardingPage;
}