auto_refresh_on_reconnect 0.1.0
auto_refresh_on_reconnect: ^0.1.0 copied to clipboard
A lightweight Flutter package that automatically refreshes widgets when internet connection is restored.
auto_refresh_on_reconnect #
A lightweight Flutter package that automatically refreshes widgets when internet connection is restored — without requiring developers to manually manage network listeners or rebuild the UI.
Demo #

Automatic refresh when internet connection is restored
Features #
✅ Automatic refresh on internet reconnection
✅ Real internet verification (not just WiFi connection)
✅ Debounced reconnection events to prevent rapid re-triggers
✅ Custom offline UI support
✅ State-management agnostic (works with Provider, Bloc, Riverpod, etc.)
✅ Builder-based API for data fetching
✅ Fully null-safe and tested
Installation #
Add this to your pubspec.yaml:
dependencies:
auto_refresh_on_reconnect: ^0.1.0
Then run:
flutter pub get
Usage #
Basic Usage #
Wrap your widget with AutoRefreshOnReconnect and provide an onRefresh callback:
import 'package:auto_refresh_on_reconnect/auto_refresh_on_reconnect.dart';
AutoRefreshOnReconnect(
onRefresh: () async {
// Your refresh logic here
await fetchProducts();
},
child: ProductListView(),
)
With Offline UI #
Display a custom widget when the device is offline:
AutoRefreshOnReconnect(
onRefresh: () async {
await fetchProducts();
},
offlineBuilder: (context) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.wifi_off, size: 64),
SizedBox(height: 16),
Text('No Internet Connection'),
],
),
),
child: ProductListView(),
)
Custom Debounce Duration #
Adjust the debounce duration to control how quickly the refresh triggers after reconnection:
AutoRefreshOnReconnect(
debounceDuration: Duration(seconds: 5), // Wait 5 seconds before refreshing
onRefresh: () async {
await fetchProducts();
},
child: ProductListView(),
)
Builder API #
Use the builder-based API for automatic data fetching and display:
AutoRefreshOnReconnectBuilder<List<Product>>(
futureBuilder: () => fetchProducts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
if (snapshot.hasData) {
return ProductList(products: snapshot.data!);
}
return Center(child: Text('No data'));
},
offlineBuilder: (context) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.wifi_off, size: 64),
SizedBox(height: 16),
Text('Offline - will refresh when reconnected'),
],
),
),
)
Additional Information #
Platform Support #
- ✅ Android
- ✅ iOS
- ✅ Web
- ✅ macOS
- ✅ Windows
- ✅ Linux
How It Works #
- Connectivity Monitoring: Uses
connectivity_plusto monitor network state changes - Real Internet Verification: Performs HTTP HEAD requests to verify actual internet access
- Debouncing: Prevents rapid successive refresh calls during unstable connections
- Automatic Refresh: Triggers your callback when connection is restored after being offline
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Customization Options #
Custom Connectivity Service #
For testing or custom network check implementations, you can provide your own ConnectivityService:
class CustomConnectivityService extends ConnectivityService {
@override
Future<bool> hasInternetAccess() async {
// Your custom internet check logic
return true;
}
}
AutoRefreshOnReconnect(
connectivityService: CustomConnectivityService(),
onRefresh: () async {
await fetchData();
},
child: MyWidget(),
)
Custom Check URL #
Change the URL used for internet verification:
final service = ConnectivityService(
checkUrl: 'https://example.com',
timeout: Duration(seconds: 5),
);
AutoRefreshOnReconnect(
connectivityService: service,
onRefresh: () async {
await fetchData();
},
child: MyWidget(),
)
Platform-Specific Behavior #
Web Platform #
On web platforms, the package handles CORS (Cross-Origin Resource Sharing) restrictions gracefully:
- The package relies more on the connectivity status from
connectivity_plus - HTTP HEAD requests may fail due to CORS, so the package assumes online status when connectivity is detected
- To test offline behavior on web:
- Use Chrome DevTools → Network tab → Toggle "Offline"
- Or disable your network connection
Mobile & Desktop Platforms #
On mobile (iOS/Android) and desktop (macOS/Windows/Linux) platforms:
- The package performs actual HTTP HEAD requests to verify internet access
- This provides more accurate connectivity detection
- Default check URL is
https://www.google.com(customizable)
API Reference #
AutoRefreshOnReconnect #
| Parameter | Type | Default | Description |
|---|---|---|---|
child |
Widget |
required | The widget to display when online |
onRefresh |
Future<void> Function()? |
null |
Callback triggered on reconnection |
offlineBuilder |
WidgetBuilder? |
null |
Builder for offline UI |
debounceDuration |
Duration |
Duration(seconds: 2) |
Debounce duration for reconnection |
connectivityService |
ConnectivityService? |
null |
Custom connectivity service |
AutoRefreshOnReconnectBuilder #
| Parameter | Type | Default | Description |
|---|---|---|---|
futureBuilder |
Future<T> Function() |
required | Function that returns data |
builder |
AsyncWidgetBuilder<T> |
required | Builder receiving AsyncSnapshot |
offlineBuilder |
WidgetBuilder? |
null |
Builder for offline UI |
debounceDuration |
Duration |
Duration(seconds: 2) |
Debounce duration |
connectivityService |
ConnectivityService? |
null |
Custom connectivity service |
Example #
A complete example app is available in the example/ directory, demonstrating:
- Real API calls with JSONPlaceholder
- Both widget and builder APIs
- Custom offline UI with loading states
- Navigation between different screens
- Error handling and refresh counters
To run the example:
cd example
flutter run
See the example README for detailed instructions.
Testing #
The package includes comprehensive tests. Run them with:
flutter test
Testing Your Implementation #
When testing widgets that use AutoRefreshOnReconnect, you can provide a mock connectivity service:
class MockConnectivityService extends ConnectivityService {
final StreamController<bool> _controller = StreamController<bool>.broadcast();
bool _isConnected = true;
@override
Stream<bool> get onConnectivityChanged => _controller.stream;
@override
Future<bool> hasInternetAccess() async => _isConnected;
void setConnected(bool connected) {
_isConnected = connected;
_controller.add(connected);
}
}
// In your test
final mockService = MockConnectivityService();
await tester.pumpWidget(
AutoRefreshOnReconnect(
connectivityService: mockService,
onRefresh: () async {
// Your refresh logic
},
child: YourWidget(),
),
);
// Simulate going offline
mockService.setConnected(false);
await tester.pumpAndSettle();
// Simulate reconnection
mockService.setConnected(true);
await tester.pumpAndSettle();
Example App #
Check out the example directory for a complete working example demonstrating:
- Basic auto-refresh functionality with real API calls (JSONPlaceholder)
- Custom offline UI with icons and messages
- Refresh counter and timestamp tracking
- Builder API usage with user data
- Error handling and loading states
- Navigation between examples
To run the example:
cd example
flutter run -d chrome # For web
# or
flutter run # For mobile/desktop
The example fetches real data from JSONPlaceholder API:
- Main screen: Fetches posts
- Builder example: Fetches users
State Management Integration #
This package is state-management agnostic and works seamlessly with any solution:
With Provider #
AutoRefreshOnReconnect(
onRefresh: () async {
await context.read<ProductProvider>().fetchProducts();
},
child: Consumer<ProductProvider>(
builder: (context, provider, child) {
return ProductList(products: provider.products);
},
),
)
With Bloc #
AutoRefreshOnReconnect(
onRefresh: () async {
context.read<ProductBloc>().add(FetchProducts());
},
child: BlocBuilder<ProductBloc, ProductState>(
builder: (context, state) {
if (state is ProductLoaded) {
return ProductList(products: state.products);
}
return CircularProgressIndicator();
},
),
)
With Riverpod #
class ProductScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return AutoRefreshOnReconnect(
onRefresh: () async {
ref.invalidate(productsProvider);
},
child: Consumer(
builder: (context, ref, child) {
final products = ref.watch(productsProvider);
return products.when(
data: (data) => ProductList(products: data),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
);
},
),
);
}
}
See CHANGELOG.md for a list of changes.