Saltar al contenido principal

Connectivity Plus. Muestra a tus usuarios si tienen conexión a internet

· 4 min de lectura
Yayo Arellano
Software Engineer
Youtube video player

Youtube video player

Tienes una aplicación y te gustaría mostrar a los usuarios una advertencia cuando el dispositivo pierde conexión a internet como en la siguiente imagen:

Banner: Sin conexión a internet

Banner: Sin conexión a internet

Bueno, es mucho más fácil de lo que parece, pero antes de comenzar puedes descargar el código fuente de Github o puedes ver el videotutorial en YouTube.

note

En este artículo utilizaremos ValueNotifier para mostrar a los usuarios si no hay conexión. Ejemplos con Cubit, GetX y Provider están disponibles en el videotutorial de YouTube.

Requisitos

Connectivity Plus: Es un paquete que nos dice cuando hay un cambio en la red. Por ejemplo cuando te conectas o desconectas a una red utilizando wifi. Es importante recordar que este paquete por sí solo no nos dice si hay o no conexión a internet. RxDart: Nos va a ayudar a emitir estados anteriores del estado de la conexión.

Para saber si hay o no conexión a internet vamos a utilizar la solución que pueden encontrar en stackoverflow.

1- Agregar dependencias

En el archivo pubspec.yaml agregamos los siguientes paquetes:

dependencies:
flutter:
sdk: flutter

rxdart: ^0.27.3
connectivity_plus: ^2.3.0

2- Verificar conexión a internet.

Creamos un enum para saber el estado de la conexión actual.

enum ConnectionStatus {
online,
offline,
}

Creamos una clase que nos va a ayudar a verificar el estado de la conexión y emitir nuevos estados si esta cambia.

class CheckInternetConnection {
final Connectivity _connectivity = Connectivity();

// El estado por defecto sera Online. Este controlador nos va
// ayudar a emitir nuevos estados cuando la conexion cambie.
final _controller = BehaviorSubject.seeded(ConnectionStatus.online);
StreamSubscription? _connectionSubscription;

CheckInternetConnection() {
_checkInternetConnection();
}

// La clase [ConnectionStatusValueNotifier] va suscribirse a este Stream
// y cuando la conexión cambie el status se va actualizar
Stream<ConnectionStatus> internetStatus() {
_connectionSubscription ??= _connectivity.onConnectivityChanged
.listen((_) => _checkInternetConnection());
return _controller.stream;
}

// Solución de stackoverflow
Future<void> _checkInternetConnection() async {
try {
// Algunas veces, después de conectarnos a la red, esta función
// se ejecuta cuando el dispositivo todavía no establece
// conexión a internet. Este delay de 3 segundos le da tiempo
// al dispositivo a conectarse y evitar falsos negativos.
await Future.delayed(const Duration(seconds: 3));
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
_controller.sink.add(ConnectionStatus.online);
} else {
_controller.sink.add(ConnectionStatus.offline);
}
} on SocketException catch (_) {
_controller.sink.add(ConnectionStatus.offline);
}
}

Future<void> close() async {
// Cancelamos la suscripción y cerramos el controlador
await _connectionSubscription?.cancel();
await _controller.close();
}
}

Esta clase se debe inicializar solo una vez durante todo el ciclo de vida de la app. Para este ejemplo yo la voy a inicializar de forma global en el archivo main.dart:

// Inicializar solo una vez.
final internetChecker = CheckInternetConnection();

void main() async {
runApp(
MyApp(),
);
}

3- Administrador de estados (State management)

Para mantener el estado vamos a utilizar ValueNotifier así que creamos la siguiente clase:

class ConnectionStatusValueNotifier extends ValueNotifier<ConnectionStatus> {
// Nos ayuda a mantener una suscripción con la
// clase [CheckInternetConnection]
late StreamSubscription _connectionSubscription;

ConnectionStatusValueNotifier() : super(ConnectionStatus.online) {
// Cada vez que se emite un nuevos estado actualizamos [value]
// esto va hacer que nuestro widget se vuelva a construir.
_connectionSubscription = internetChecker
.internetStatus()
.listen((newStatus) => value = newStatus);
}


void dispose() {
// Cancelamos la subscription
_connectionSubscription.cancel();
super.dispose();
}
}

4- Widget para mostrar que no hay conexión

Creamos el widget que utilizará ValueListenableBuilder para escuchar los valores emitidos por la clase ConnectionStatusValueNotifier

class WarningWidgetValueNotifier extends StatelessWidget {
const WarningWidgetValueNotifier({Key? key}) : super(key: key);


Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: ConnectionStatusValueNotifier(),
builder: (context, ConnectionStatus status, child) {
return Visibility(
visible: status != ConnectionStatus.online,
child: Container(
padding: const EdgeInsets.all(16),
height: 60,
color: Colors.brown,
child: Row(
children: [
const Icon(Icons.wifi_off),
const SizedBox(width: 8),
const Text('No internet connection.'),
],
),
),
);
},
);
}
}

5- Mostrar cuando no hay conexión

Ahora solo tenemos que agregar este widget en cualquier pantalla donde queremos que se muestre la advertencia. Por ejemplo:

class MyApp extends StatelessWidget {
const MyApp();


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Value notifier Example'),
),
body: Column(
children: <Widget>[
const WarningWidgetValueNotifier(),
const Text('Abigail'),
const Text('Alexandra'),
const Text('Amelia'),
],
),
);
}
}

Conclusión

Mostrar a tus usuarios que no tienen conexión a internet es mucho más fácil de lo que parece y no es necesario agregar ningún paquete para manejar estados.