Perché gestire lo stato della rete
Un'app mobile professionale deve funzionare bene anche quando la connessione è instabile o assente. Ignorare gli stati offline porta a errori improvvisi, spinner infiniti e utenti frustrati. In questo articolo vediamo come rilevare e reagire ai cambiamenti di connettività in Flutter usando il pacchetto connectivity_plus, integrandolo con un controllo reale della raggiungibilità di Internet.
connectivity_plus: cosa fa e cosa NON fa
Il pacchetto connectivity_plus (mantenuto dalla community Flutter) permette di sapere a quale tipo di rete è collegato il dispositivo: WiFi, dati mobili, ethernet o nessuna.
Attenzione a un equivoco comune: connectivity_plus indica solo la presenza di un'interfaccia di rete attiva, non se Internet è realmente raggiungibile. Un utente può essere connesso al WiFi di un aeroporto senza aver superato il captive portal: la connettività risulta wifi, ma le richieste HTTP falliscono. Per questo lo abbineremo a un controllo effettivo.
Installazione
dependencies:
connectivity_plus: ^6.0.5
internet_connection_checker_plus: ^2.5.2
Rilevare il tipo di connessione
import 'package:connectivity_plus/connectivity_plus.dart';
Future<void> checkConnection() async {
final result = await Connectivity().checkConnectivity();
if (result.contains(ConnectivityResult.mobile)) {
print('Connesso tramite dati mobili');
} else if (result.contains(ConnectivityResult.wifi)) {
print('Connesso tramite WiFi');
} else if (result.contains(ConnectivityResult.none)) {
print('Nessuna connessione di rete');
}
}
Dalla versione 6, checkConnectivity() restituisce una List<ConnectivityResult> perché un dispositivo può avere più interfacce attive contemporaneamente.
Ascoltare i cambiamenti in tempo reale
Possiamo ascoltare uno stream che emette un evento a ogni cambio di stato:
late final StreamSubscription<List<ConnectivityResult>> _subscription;
void startListening() {
_subscription = Connectivity().onConnectivityChanged.listen(
(List<ConnectivityResult> results) {
final isOffline = results.contains(ConnectivityResult.none);
print(isOffline ? 'Offline' : 'Online');
},
);
}
void dispose() {
_subscription.cancel();
}
Ricordati sempre di annullare la sottoscrizione per evitare memory leak.
Un servizio robusto per lo stato online reale
Combiniamo il tipo di connessione con la verifica della raggiungibilità di Internet, esponendo uno Stream<bool> semplice da consumare in tutta l'app.
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
class NetworkService {
final _controller = StreamController<bool>.broadcast();
StreamSubscription? _connectivitySub;
Stream<bool> get onStatusChange => _controller.stream;
void init() {
_connectivitySub =
Connectivity().onConnectivityChanged.listen((_) => _updateStatus());
_updateStatus();
}
Future<void> _updateStatus() async {
final results = await Connectivity().checkConnectivity();
if (results.contains(ConnectivityResult.none)) {
_controller.add(false);
return;
}
// Verifica reale: c'è davvero Internet?
final hasInternet = await InternetConnection().hasInternetAccess;
_controller.add(hasInternet);
}
void dispose() {
_connectivitySub?.cancel();
_controller.close();
}
}
Mostrare un banner offline nella UI
Un pattern efficace è un banner persistente che appare solo quando l'utente perde la connessione:
class ConnectionBanner extends StatelessWidget {
final NetworkService service;
const ConnectionBanner({super.key, required this.service});
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
stream: service.onStatusChange,
initialData: true,
builder: (context, snapshot) {
final isOnline = snapshot.data ?? true;
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
height: isOnline ? 0 : 40,
color: Colors.red.shade700,
alignment: Alignment.center,
child: isOnline
? null
: const Text(
'Nessuna connessione a Internet',
style: TextStyle(color: Colors.white),
),
);
},
);
}
}
Best practice per una strategia offline-first
- Non bloccare l'interazione: mostra dati in cache invece di uno spinner infinito.
- Distingui "interfaccia attiva" da "Internet raggiungibile": verifica sempre con una richiesta reale prima di operazioni critiche.
- Fai debounce degli eventi: durante i cambi di rete lo stream può emettere più eventi ravvicinati; applica un piccolo
debounceper evitare flicker della UI. - Metti in coda le operazioni: salva localmente le azioni fallite (es. con una tabella pending) e riprovale quando torna la connessione.
- Testa gli scenari reali: modalità aereo, WiFi senza Internet, passaggio WiFi/dati mobili.
Conclusione
Gestire correttamente lo stato della rete è un tassello fondamentale per app affidabili. Con connectivity_plus per il tipo di connessione e un controllo di raggiungibilità reale ottieni uno stato online affidabile, base ideale per costruire esperienze offline-first che non lasciano mai l'utente bloccato.
