Network Monitoring System Documentation

Overview

The Network Monitoring System provides a comprehensive solution for monitoring network connectivity in Flutter applications using Riverpod providers. It includes automatic network status checking, widget mixins for easy integration, and alert management.

Features

  • Automatic Network Monitoring: Periodic checks using InternetChecker
  • Riverpod Integration: Clean state management with providers
  • Widget Mixins: Easy integration with existing widgets
  • Alert System: Automatic network alerts via AlertManager
  • Error Handling: Robust error reporting and recovery
  • Testing Support: Comprehensive test utilities

Core Components

1. NetworkServiceProvider

The main provider that manages network status monitoring:

// Access network state
final networkState = ref.watch(networkServiceProvider);

// Check if online
final isOnline = ref.watch(isOnlineProvider);

// Get current status
final status = ref.watch(networkStatusProvider);

2. NetworkServiceState

Immutable state object representing network status:

class NetworkServiceState {
  final NetworkStatus networkStatus;
  bool get isOnline => networkStatus == NetworkStatus.online;
}

3. Widget Mixins

Three different mixins for different use cases:

NetworkMonitorMixin (Full Monitoring + Alerts)

class MyWidget extends StatefulWidget {
  // ... widget implementation
}

class _MyWidgetState extends State<MyWidget> with NetworkMonitorMixin {
  @override
  bool get sendNetworkAlerts => true; // Enable alerts

  @override
  void onNetworkStatusChanged(NetworkStatus status) {
    // Custom handling of network changes
    print('Network changed to: $status');
  }

  @override
  Widget buildWithNetworkMonitoring(BuildContext context, WidgetRef ref, Widget? child) {
    final isOnline = ref.watch(isOnlineProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text(isOnline ? 'Online' : 'Offline'),
      ),
      body: YourWidgetContent(),
    );
  }
}

NetworkMonitorUtilsMixin (Enhanced Utilities)

class _MyWidgetState extends State<MyWidget>
    with NetworkMonitorMixin, NetworkMonitorUtilsMixin {

  void _handleRefresh() async {
    // Force a network check
    await forceNetworkCheck(ref);

    // Check current status
    if (isCurrentlyOnline(ref)) {
      // Perform online actions
    }
  }

  void _testOfflineMode() {
    // Manually set status for testing
    setNetworkStatus(ref, NetworkStatus.offline);
  }
}

NetworkAwareMixin (Simple Status Access)

class _MyWidgetState extends State<MyWidget> with NetworkAwareMixin {
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        final isOnline = this.isOnline(ref);

        return Container(
          color: isOnline ? Colors.green : Colors.red,
          child: Text(isOnline ? 'Connected' : 'Disconnected'),
        );
      },
    );
  }
}

Quick Start Guide

Step 1: Wrap your app with ProviderScope

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

Step 2: Use network providers in your widgets

class NetworkStatusWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final isOnline = ref.watch(isOnlineProvider);
    final status = ref.watch(networkStatusProvider);

    return Card(
      child: ListTile(
        leading: Icon(
          isOnline ? Icons.wifi : Icons.wifi_off,
          color: isOnline ? Colors.green : Colors.red,
        ),
        title: Text('Network Status'),
        subtitle: Text('Status: ${status.name}'),
      ),
    );
  }
}

Step 3: Add network monitoring to existing widgets

// Before
class _MyPageState extends State<MyPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(/* ... */);
  }
}

// After
class _MyPageState extends State<MyPage> with NetworkMonitorMixin {
  @override
  Widget buildWithNetworkMonitoring(BuildContext context, WidgetRef ref, Widget? child) {
    return Scaffold(/* ... */);
  }
}

Advanced Usage

Custom Network Monitoring

class _CustomNetworkWidgetState extends State<CustomNetworkWidget>
    with NetworkMonitorMixin {

  @override
  bool get sendNetworkAlerts => false; // Disable automatic alerts

  @override
  bool get logNetworkChanges => true; // Enable logging

  @override
  void onNetworkStatusChanged(NetworkStatus status) {
    super.onNetworkStatusChanged(status);

    // Custom logic for network changes
    switch (status) {
      case NetworkStatus.online:
        _syncData();
        break;
      case NetworkStatus.offline:
        _enableOfflineMode();
        break;
      case NetworkStatus.unknown:
        _showConnectivityWarning();
        break;
    }
  }
}

Manual Network Control

class NetworkTestWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            final notifier = ref.read(networkServiceNotifierProvider);
            notifier.forceCheck();
          },
          child: Text('Force Check'),
        ),
        ElevatedButton(
          onPressed: () {
            final notifier = ref.read(networkServiceNotifierProvider);
            notifier.updateStatus(NetworkStatus.offline);
          },
          child: Text('Simulate Offline'),
        ),
      ],
    );
  }
}

Testing

Unit Testing Providers

test('should update network status', () {
  final container = ProviderContainer();
  final notifier = container.read(networkServiceNotifierProvider);

  // Set to online
  notifier.updateStatus(NetworkStatus.online);

  expect(container.read(isOnlineProvider), true);
  expect(container.read(networkStatusProvider), NetworkStatus.online);

  container.dispose();
});

Widget Testing with Network States

testWidgets('should show correct UI based on network status', (tester) async {
  await tester.pumpWidget(
    ProviderScope(
      child: MaterialApp(
        home: MyNetworkWidget(),
      ),
    ),
  );

  // Find the provider container
  final container = ProviderScope.containerOf(
    tester.element(find.byType(MyNetworkWidget)),
  );

  // Simulate network change
  final notifier = container.read(networkServiceNotifierProvider);
  notifier.updateStatus(NetworkStatus.offline);

  await tester.pump();

  // Verify UI updates
  expect(find.text('Offline'), findsOneWidget);
});

Configuration

InternetChecker Settings

The network monitoring uses InternetChecker with configurable intervals:

// From internet_checker.dart
InternetChecker._internal()
  : checkInterval = kCheckNetwork,          // Normal check interval
    checkTimeout = kCheckNetworkWhenTimeout, // Timeout duration
    checkDownInterval = kCheckNetworkWhenDown, // Check interval when down
    addresses = kNetworkCheckAddresses;    // Custom check addresses

Alert Configuration

Network alerts are automatically sent to kAlertManager. To customize:

class _MyWidgetState extends State<MyWidget> with NetworkMonitorMixin {
  @override
  bool get sendNetworkAlerts => false; // Disable alerts

  @override
  void onNetworkStatusChanged(NetworkStatus status) {
    // Send custom alerts
    if (status == NetworkStatus.offline) {
      showDialog(/* custom offline dialog */);
    }
  }
}

Best Practices

1. Choose the Right Mixin

  • NetworkMonitorMixin: Use when you need alerts and monitoring
  • NetworkMonitorUtilsMixin: Use when you need advanced utilities
  • NetworkAwareMixin: Use for simple status checking

2. Handle Network Changes Gracefully

@override
void onNetworkStatusChanged(NetworkStatus status) {
  switch (status) {
    case NetworkStatus.online:
      // Resume operations
      _resumeDataSync();
      _hideOfflineIndicator();
      break;
    case NetworkStatus.offline:
      // Pause operations
      _pauseDataSync();
      _showOfflineIndicator();
      break;
    case NetworkStatus.unknown:
      // Handle uncertainty
      _showConnectivityWarning();
      break;
  }
}

3. Optimize Performance

// Only monitor in widgets that need it
class _NonNetworkWidgetState extends State<NonNetworkWidget> {
  // Don't use network mixins if not needed
}

// Use Consumer only where needed
Widget build(BuildContext context) {
  return Column(
    children: [
      StaticWidget(), // No Consumer needed
      Consumer(
        builder: (context, ref, child) {
          final isOnline = ref.watch(isOnlineProvider);
          return NetworkDependentWidget(isOnline: isOnline);
        },
      ),
    ],
  );
}

4. Error Handling

@override
void onNetworkStatusChanged(NetworkStatus status) {
  try {
    // Handle network change
    _handleNetworkChange(status);
  } catch (e, stackTrace) {
    LOG.e('Failed to handle network change', error: e, stackTrace: stackTrace);
    // Fallback behavior
    _handleNetworkError();
  }
}

Troubleshooting

Common Issues

  1. Providers not updating: Ensure ProviderScope wraps your app
  2. Alerts not showing: Check sendNetworkAlerts is true and kAlertManager is initialized
  3. Memory leaks: Ensure widgets using mixins properly dispose
  4. Network checks failing: Verify internet connection and check addresses

Debug Information

// Enable debug logging
@override
bool get logNetworkChanges => true;

// Force network check for debugging
final notifier = ref.read(networkServiceNotifierProvider);
await notifier.forceCheck();

// Check current status
final status = ref.read(networkStatusProvider);
print('Current network status: $status');

Migration Guide

From Manual Network Checking

// Before
class _OldWidgetState extends State<OldWidget> {
  bool _isOnline = false;

  @override
  void initState() {
    super.initState();
    _checkNetwork();
  }

  void _checkNetwork() async {
    // Manual network checking code
  }
}

// After
class _NewWidgetState extends State<NewWidget> with NetworkAwareMixin {
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        final isOnline = this.isOnline(ref);
        // Use isOnline directly
      },
    );
  }
}

This network monitoring system provides a robust, scalable solution for handling network connectivity in Flutter applications with minimal boilerplate and maximum flexibility.

Network Service Provider Implementation Summary

Overview

Successfully implemented a comprehensive network monitoring solution with RiverPod that includes:

  1. Core Network Service Provider with timer-based monitoring
  2. Widget Mixins for easy integration with StatefulWidgets
  3. Alert System Integration with kAlertManager
  4. Complete Documentation and examples
  5. Testing Infrastructure and validation

Files Created

1. Network Service Provider (lib/providers/network/network_service_provider.dart)

  • NetworkServiceNotifier: StateNotifier that manages network status with timer-based periodic checking
  • Multiple Convenience Providers: isOnlineProvider, isOfflineProvider, networkStatusProvider, etc.
  • Timer Management: Automatic start/stop with 30-second check intervals
  • Error Handling: Comprehensive error reporting and state management

2. Network Service State (lib/providers/network/network_service_state.dart)

  • Immutable State Class: Simple data container for network status
  • isOnline Getter: Convenience method for checking online status
  • Uses NetworkStatus Enum: From core package for consistency

3. Widget Mixins (lib/providers/network/network_monitor_mixin.dart)

Three different mixin levels for various use cases:

  • Automatic provider listening with ref.listen
  • Alert generation via kAlertManager
  • Lifecycle management (initState/dispose)
  • Network state change callbacks
NetworkMonitorUtilsMixin (Enhanced)
  • Provider listening without automatic alerts
  • Custom callback handling for network changes
  • Flexible integration options
NetworkAwareMixin (Simple)
  • Basic network status access
  • Minimal overhead for simple use cases
  • Easy integration for read-only network status

4. Example Implementation (lib/providers/network/network_monitor_example.dart)

  • FullNetworkMonitorWidget: Complete implementation with alerts
  • BasicNetworkWidget: Simple network status display
  • CustomNetworkWidget: Custom callback handling

5. Test Suite (test/providers/network/)

  • Unit Tests: Mock-based testing for core functionality
  • Provider Integration Tests: Flutter test environment validation
  • Validation: Successfully runs and passes all tests

6. Documentation (lib/providers/network/README.md)

  • Complete Setup Guide: Step-by-step implementation
  • Usage Examples: All three mixin patterns
  • Best Practices: Performance and reliability guidelines
  • Troubleshooting: Common issues and solutions

Key Features

Timer-Based Network Monitoring

// Automatic 30-second interval checking
Timer.periodic(const Duration(seconds: 30), (_) async {
  await checkNetworkStatus();
});

Multiple Provider Access Patterns

// Direct state access
final networkState = ref.watch(networkServiceProvider);

// Convenience providers
final isOnline = ref.watch(isOnlineProvider);
final isOffline = ref.watch(isOfflineProvider);

Widget Integration Options

// Option 1: Full featured with alerts
class MyWidget extends StatefulWidget with NetworkMonitorMixin

// Option 2: Enhanced with custom callbacks
class MyWidget extends StatefulWidget with NetworkMonitorUtilsMixin

// Option 3: Simple read-only access
class MyWidget extends StatefulWidget with NetworkAwareMixin

Alert System Integration

// Automatic alerts sent to kAlertManager
void _sendNetworkAlert(bool isOnline) {
  kAlertManager.send(NetworkAlertInfo(
    isOnline: isOnline,
    timestamp: DateTime.now(),
  ));
}

Usage Examples

Basic Implementation

class MyNetworkWidget extends StatefulWidget with NetworkMonitorMixin {
  @override
  Widget build(BuildContext context) {
    final networkState = networkServiceState;
    return Text(networkState.isOnline ? 'Online' : 'Offline');
  }
}

Custom Callback Implementation

class CustomNetworkWidget extends StatefulWidget with NetworkMonitorUtilsMixin {
  @override
  void onNetworkChanged(NetworkServiceState state) {
    if (!state.isOnline) {
      // Handle offline state
      showOfflineMessage();
    }
  }
}

Integration Notes

Provider Registration

// Add to main.dart providers
networkServiceNotifierProvider,
networkServiceProvider,
isOnlineProvider,
isOfflineProvider,
// ... other convenience providers

Error Handling

  • Network check failures are caught and logged
  • State remains in last known state during errors
  • Timer continues running for automatic recovery

Performance Considerations

  • 30-second check interval balances responsiveness vs battery life
  • Providers use StateNotifier for efficient state updates
  • Mixins provide lightweight integration options
  • Timer management prevents memory leaks

Future Enhancements

  • Configurable check intervals
  • Network quality metrics
  • Connectivity type detection
  • Historical network state tracking
  • Custom alert types and priorities