Connectivity plus. Show your users if they have internet connection
Do you have a Flutter App, and would you like to show the users when they are offline, like in the next image?
Before we start, you can download the source code from GitHub. The source code has examples using: cubit (flutter bloc), getx, ChangeNotifier (provider), and ValueNotifier.
In this tutorial, we will only use ValueNotifier, so you will not have to add any state management package.
Requirements
Connectivity Plus: This plugin allows Flutter apps to discover network connectivity. For example, when you are connected or disconnected from Wi-Fi. But this package will not tell us if we have an internet connection or not. RxDart: We will use it to keep the connection state and emit a new connection status.
To know if we have an internet connection, we will check this code from stackoverflow.
1- Add dependencies
Go to the file pubspec.yaml
and add the following packages.
dependencies:
flutter:
sdk: flutter
rxdart: ^0.27.3
connectivity_plus: ^2.3.0
2- Verify if we have an internet connection.
First, we create an enum to know the current internet status.
enum ConnectionStatus {
online,
offline,
}
Then we create a class to help us check the internet connection. Every time the network status change, this class will emit a new connection status.
class CheckInternetConnection {
final Connectivity _connectivity = Connectivity();
// Default will be online. This controller will help to emit new states when the connection changes.
final _controller = BehaviorSubject.seeded(ConnectionStatus.online);
StreamSubscription? _connectionSubscription;
CheckInternetConnection() {
_checkInternetConnection();
}
// The [ConnectionStatusValueNotifier] will subscribe to this
// stream and every time the connection status changes it
// will update its value
Stream<ConnectionStatus> internetStatus() {
_connectionSubscription ??= _connectivity.onConnectivityChanged
.listen((_) => _checkInternetConnection());
return _controller.stream;
}
// Code from StackOverflow
Future<void> _checkInternetConnection() async {
try {
// Sometimes, after we connect to a network, this function will
// be called but the device still does not have an internet connection.
// This 3 seconds delay will give some time to the device to
// connect to the internet in order to avoid false-positives
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 {
// Cancel subscription and close controller
await _connectionSubscription?.cancel();
await _controller.close();
}
}
This class has to be initialized only one time during the lifecycle of the app. In this example, I will initialize
as a global variable inside the main.dart
file:
// Initialize only one time
final internetChecker = CheckInternetConnection();
void main() async {
runApp(
MyApp(),
);
}
3- State management
To keep the state we are going to use ValueNotifier
so we are going to create a new class:
class ConnectionStatusValueNotifier extends ValueNotifier<ConnectionStatus> {
// Will keep a subscription to
// the class [CheckInternetConnection]
late StreamSubscription _connectionSubscription;
ConnectionStatusValueNotifier() : super(ConnectionStatus.online) {
// Everytime there a new connection status is emitted
// we will update the [value]. This will make the widget
// to rebuild
_connectionSubscription = internetChecker
.internetStatus()
.listen((newStatus) => value = newStatus);
}
void dispose() {
_connectionSubscription.cancel();
super.dispose();
}
}
4- No internet connection Widget
We will create the widget that will use a ValueListenableBuilder
to listen for the statuses emitted by
the class 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- Usage of the widget: WarningWidgetValueNotifier
To show the user there if there is no internet connection, we have to add the WarningWidgetValueNotifier
widget on
any screen that we would like to show the warning. For example:
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'),
],
),
);
}
}
Conclusion
Showing the users of your app if they are offline is very easy to implement. We did not even have to add complex packages or state management dependencies.