Do you have a Flutter App and you would 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 are only going to use ValueNotifier so you will not have to add any state management package.
Requiriments
Connectivity Plus: This plugin allows Flutter apps to discover network connectivity. Example when you are connected or disconnected from wifi. But this package will not tell us if we have or not internet connection.
RxDart: We will use it to keep the connection status and emit new connection status.
To know if we have internet connection we will check this code from stackoverflow.
1- Add dependencies
Go to the file pubspec.yaml
and add the next packages
dependencies:
flutter:
sdk: flutter
rxdart: ^0.27.3
connectivity_plus: ^2.3.0
2- Verify if we have internet connection.
First we create an enum to know the current internet status.
enum ConnectionStatus {
online,
offline,
}
Then we create a class that will help us to check the internet connection. Everytime 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 everytime the connection status change it
// will update it's 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 do not have 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
Now we are going to create the widget that will use a ValueListenableBuilder
to listen for the statuses emmited 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 just have to add the WarningWidgetValueNotifier
widget in 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 to 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.
I made a video (in spanish) to show the end result:
0 comments:
Post a Comment