J'ai un appel réseau à exécuter. Mais avant cela, je dois vérifier si le périphérique dispose d'une connexion Internet.
Voici ce que j'ai fait jusqu'à présent:
var connectivityResult = new Connectivity().checkConnectivity();// User defined class
if (connectivityResult == ConnectivityResult.mobile ||
connectivityResult == ConnectivityResult.wifi) {*/
this.getData();
} else {
neverSatisfied();
}
La méthode ci-dessus ne fonctionne pas.
Le plug-in connectivity
indique dans sa documentation qu'il ne fournit des informations que s'il existe une connexion réseau, mais pas si le réseau est connecté à Internet.
Notez que sur Android, cela ne garantit pas la connexion à Internet. Par exemple, l'application peut avoir un accès wifi, mais il peut s'agir d'un VPN ou d'un WiFi d'hôtel sans accès.
Vous pouvez utiliser
import 'Dart:io';
...
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
}
} on SocketException catch (_) {
print('not connected');
}
Pour ceux qui arrivent ici, j'aimerais ajouter quelque chose à la réponse de Günter Zöchbauer: telle était ma solution pour implémenter un utilitaire: savoir s'il existe un accès à Internet ou non.
Avertissement:
Dart et Flutter sont nouveaux pour moi, donc ce n’est peut-être pas la meilleure approche, mais j'aimerais beaucoup avoir vos commentaires.
Mes exigences
Je ne voulais pas avoir un tas de code répété n'importe où j'avais besoin de vérifier la connexion et je voulais qu'il mette à jour automatiquement les composants ou tout ce qui se souciait de la connexion chaque fois qu'il y avait un changement.
Nous avons d'abord installé un Singleton. Si vous ne connaissez pas ce modèle, vous trouverez en ligne de nombreuses informations intéressantes à leur sujet. Mais, selon l’essentiel, vous souhaitez créer une instance unique d’une classe au cours du cycle de vie d’une application et pouvoir l’utiliser n’importe où.
Ce singleton s'accroche à flutter_connectivity
et écoute les modifications de connectivité, puis teste la connexion réseau, puis utilise une StreamController
pour mettre à jour tout ce qui est important.
Cela ressemble à ceci:
import 'Dart:io'; //InternetAddress utility
import 'Dart:async'; //For StreamController/Stream
import 'package:connectivity/connectivity.Dart';
class ConnectionStatusSingleton {
//This creates the single instance by calling the `_internal` constructor specified below
static final ConnectionStatusSingleton _singleton = new ConnectionStatusSingleton._internal();
ConnectionStatusSingleton._internal();
//This is what's used to retrieve the instance through the app
static ConnectionStatusSingleton getInstance() => _singleton;
//This tracks the current connection status
bool hasConnection = false;
//This is how we'll allow subscribing to connection changes
StreamController connectionChangeController = new StreamController.broadcast();
//flutter_connectivity
final Connectivity _connectivity = Connectivity();
//Hook into flutter_connectivity's Stream to listen for changes
//And check the connection status out of the gate
void initialize() {
_connectivity.onConnectivityChanged.listen(_connectionChange);
checkConnection();
}
Stream get connectionChange => connectionChangeController.stream;
//A clean up method to close our StreamController
// Because this is meant to exist through the entire application life cycle this isn't
// really an issue
void dispose() {
connectionChangeController.close();
}
//flutter_connectivity's listener
void _connectionChange(ConnectivityResult result) {
checkConnection();
}
//The test to actually see if there is a connection
Future<bool> checkConnection() async {
bool previousConnection = hasConnection;
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
hasConnection = true;
} else {
hasConnection = false;
}
} on SocketException catch(_) {
hasConnection = false;
}
//The connection status changed send out an update to all listeners
if (previousConnection != hasConnection) {
connectionChangeController.add(hasConnection);
}
return hasConnection;
}
}
Initialisation
Nous devons d’abord nous assurer d’appeler l’initialisation de notre singleton. Mais seulement une fois . Ceci vous sépare mais je l'ai fait dans la fonction main()
de mon application:
void main() {
ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
connectionStatus.initialize();
runApp(MyApp());
//Call this if initialization is occuring in a scope that will end during app lifecycle
//connectionStatus.dispose();
}
Dans Widget
ou ailleurs
import 'Dart:async'; //For StreamSubscription
...
class MyWidgetState extends State<MyWidget> {
StreamSubscription _connectionChangeStream;
bool isOffline = false;
@override
initState() {
super.initState();
ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
_connectionChangeStream = connectionStatus.connectionChange.listen(connectionChanged);
}
void connectionChanged(dynamic hasConnection) {
setState(() {
isOffline = !hasConnection;
});
}
@override
Widget build(BuildContext ctxt) {
...
}
}
J'espère que quelqu'un d'autre trouve cela utile!
Exemple de repo github: https://github.com/dennmat/flutter-connectiontest-example
Basculer en mode avion dans l'émulateur pour voir le résultat
Après @dennmatt answer , j’ai remarqué que InternetAddress.lookup
pouvait donner de bons résultats même si la connexion Internet était désactivée. Je l’ai testée en le connectant depuis mon simulateur à mon réseau WiFi domestique, puis en débranchant le câble de mon routeur. Je pense que la raison en est que le routeur met en cache les résultats de la recherche de domaine, de sorte qu'il n'a pas à interroger les serveurs DNS à chaque demande de recherche.
Quoi qu'il en soit, si vous utilisez Firestore comme moi, vous pouvez remplacer le bloc try-SocketException-catch par une transaction vide et intercepter TimeoutExceptions:
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;
}
Veuillez également noter que previousConnection
est défini avant la vérification asynchrone intenet, donc théoriquement, si checkConnection()
est appelé plusieurs fois dans un court laps de temps, il pourrait y avoir plusieurs hasConnection=true
dans une ligne ou plusieurs hasConnection=false
dans une ligne . bien sûr si @dennmatt l'a fait exprès ou non, mais dans notre cas d'utilisation, il n'y a pas eu d'effets secondaires (setState
n'a été appelé que deux fois avec la même valeur).
En utilisant
dependencies:
connectivity: ^0.4.2
ce que nous avons obtenu de ressources est
import 'package:connectivity/connectivity.Dart';
Future<bool> check() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
return true;
} else if (connectivityResult == ConnectivityResult.wifi) {
return true;
}
return false;
}
L'avenir est peu problématique pour moi, nous devons le mettre en œuvre à chaque fois comme:
check().then((intenet) {
if (intenet != null && intenet) {
// Internet Present Case
}
// No-Internet Case
});
Donc, pour résoudre ce problème, j'ai créé une classe qui accepte une fonction avec un paramètre boolean isNetworkPresent comme celui-ci.
methodName(bool isNetworkPresent){}
Et la classe utilitaire est
import 'package:connectivity/connectivity.Dart'; class NetworkCheck { Future<bool> check() async { var connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult == ConnectivityResult.mobile) { return true; } else if (connectivityResult == ConnectivityResult.wifi) { return true; } return false; } dynamic checkInternet(Function func) { check().then((intenet) { if (intenet != null && intenet) { func(true); } else{ func(false); } }); } }
Et utiliser connectivity-check utilty
fetchPrefrence(bool isNetworkPresent) {
if(isNetworkPresent){
}else{
}
}
je vais utiliser cette syntaxe
NetworkCheck networkCheck = new NetworkCheck();
networkCheck.checkInternet(fetchPrefrence)