Nothing frustrates a user more than an app that silently fails. When the internet connection drops, a well-designed Flutter app should immediately and clearly inform the user. This not only prevents confusion but also significantly improves the user experience. In this comprehensive guide, we’ll explore how to automatically show an offline message in your Flutter application, ensuring your users are never left in the dark.
At FlutterStuff.com, we’re all about providing practical, in-depth tutorials to help you build better apps. Let’s dive in!
Why Bother with an Offline Message?
Imagine a user trying to make a purchase, submit a form, or load new content. If their internet connection is unstable and your app doesn’t react, they might assume the app is broken. This can lead to negative reviews and uninstalls.
By implementing an automatic offline notification, you:
- Provide immediate feedback: Users instantly know why certain features aren’t working.
- Reduce user frustration: Clear communication prevents users from getting annoyed with your app.
- Improve perceived reliability: An app that handles offline scenarios gracefully feels more professional and robust.
- Guide user behavior: You can suggest they check their connection or even provide offline functionality.
Choosing the Right Tool for the Job: connectivity_plus
vs. internet_connection_checker_plus
Before we jump into the code, it’s crucial to understand the tools at our disposal. The two most popular packages for checking internet connectivity in Flutter are connectivity_plus
and internet_connection_checker_plus
.
connectivity_plus
: This package, maintained by the Flutter team, is excellent for determining the type of network connection (e.g., WiFi, cellular, or none). However, it has a significant limitation: being connected to a Wi-Fi network doesn’t guarantee internet access. Think of a public Wi-Fi that requires a login; you’re connected, but you can’t access the internet.internet_connection_checker_plus
: This package takes it a step further. It actively checks for an internet connection by trying to connect to a list of predefined or custom addresses. This gives you a more reliable “true” or “false” indication of whether the device can actually access the internet.
So, which one should you use?
For a simple indication of whether the device is connected to a network, connectivity_plus
is sufficient. For a definitive answer on whether there’s an active internet connection, internet_connection_checker_plus
is the way to go.
For this tutorial, we’ll focus on internet_connection_checker_plus
to build a robust offline notification system.
Step-by-Step: Implementing an Automatic Offline Banner
Let’s get our hands dirty and build a system that automatically displays a banner when the user goes offline and hides it when the connection is restored.
Step 1: Add the Dependency
First, add internet_connection_checker_plus
to your pubspec.yaml
file:
YAML
dependencies:
flutter:
sdk: flutter
internet_connection_checker_plus: ^2.3.0 # Use the latest version
DartThen, run flutter pub get
in your terminal to install the package.
Step 2: Create a Connectivity Service
It’s a good practice to encapsulate the connectivity logic in a separate service class. This makes your code cleaner and easier to manage.
Create a new file, connectivity_service.dart
, and add the following code:
Dart
import 'dart:async';
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
class ConnectivityService {
final InternetConnection _internetConnection = InternetConnection();
Stream<InternetStatus> get connectionStream => _internetConnection.onStatusChange;
}
DartThis service exposes a Stream
that will emit a new InternetStatus
(connected
or disconnected
) whenever the connectivity state changes.
Step 3: Integrate with Your App’s UI
Now, let’s consume this stream in our main application widget and display a banner accordingly. We’ll use a StreamBuilder
to listen for changes and update the UI.
In your main.dart
or your root widget, you can wrap your Scaffold
with a StreamBuilder
:
Dart
import 'package:flutter/material.dart';
import 'package:internet_connection_checker_plus/internet_connection_checker_plus.dart';
import 'connectivity_service.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Offline Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final ConnectivityService _connectivityService = ConnectivityService();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Offline Message Demo'),
),
body: StreamBuilder<InternetStatus>(
stream: _connectivityService.connectionStream,
builder: (context, snapshot) {
final status = snapshot.data;
final isOffline = status == InternetStatus.disconnected;
return Column(
children: [
if (isOffline)
Container(
width: double.infinity,
color: Colors.red,
padding: const EdgeInsets.all(8.0),
child: const Text(
'You are currently offline.',
style: TextStyle(color: Colors.white),
textAlign: TextAlign.center,
),
),
Expanded(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'This is your main app content.',
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Your button action
},
child: const Text('Perform Action'),
),
],
),
),
),
],
);
},
),
);
}
}
DartIn this example:
- We create an instance of our
ConnectivityService
. - A
StreamBuilder
listens to theconnectionStream
. - When the
InternetStatus
isdisconnected
, we display a redContainer
at the top of the screen. - The rest of your app’s content is below the banner.
This approach ensures that the offline message is automatically shown or hidden based on the real-time internet connectivity status.
Best Practices for Offline UI/UX
Simply showing a banner is a good start, but for a truly great user experience, consider these best practices:
- Use Clear and Concise Messaging: Avoid technical jargon. “You’re offline” or “No internet connection” is much better than “Network request failed.”
- Offer a “Retry” Option: For critical actions, provide a button that allows the user to try again once they’re back online.
- Cache Data for Offline Access: Whenever possible, cache important data so that users can still view content even without an internet connection. This is a more advanced topic but one that significantly enhances the user experience. You can explore packages like
hive
orshared_preferences
for simple caching. - Disable UI Elements Gracefully: Instead of just letting buttons fail, disable them and provide a tooltip explaining that an internet connection is required.
- Consider a Global Overlay: For a more prominent and non-intrusive message, you can use a package like
overlay_support
to show a notification overlay that doesn’t push your content down.
Taking It Further: State Management
For larger applications, you’ll likely be using a state management solution like BLoC or Riverpod. You can integrate your connectivity service with your chosen state management approach to provide the connectivity status to any widget in your app that needs it. This prevents you from having to wrap every screen with a StreamBuilder
.
For instance, with Riverpod, you could create a StreamProvider
that exposes the connectivity status globally.
Dart
// Using Riverpod
final connectivityStatusProvider = StreamProvider<InternetStatus>((ref) {
return ConnectivityService().connectionStream;
});
DartThen, in any widget, you can listen to this provider to react to connectivity changes.
Final Thoughts
Handling internet connectivity gracefully is a hallmark of a high-quality Flutter app. By using internet_connection_checker_plus
and following the patterns we’ve discussed, you can provide a seamless and frustration-free experience for your users, even when their connection is spotty.