Search code examples
flutterclean-architecture

Internet check stream in a Flutter app with clean architecture and Cubit?


I've set up my project with clean architecture and Cubits for state management. I have also set up a NetworkInfo class in the core/network folder, which has a future method to check internet connection. I'm using it in the RepositoryImpl class, and everything is working fine. However, I'm currently struggling to add an internet check stream to continuously check internet status. I'm not sure which layer I should add the code to or how to work with streams with Cubit without violating clean architecture principles and ensuring testability of the code?

Network info -

abstract class NetworkInfo {
  Future<bool> isConnected();
}

class NetworkInfoImpl implements NetworkInfo {
  InternetConnection internetConnection;

  NetworkInfoImpl({
    required this.internetConnection,
  });

  @override
  Future<bool> isConnected() {
    // TODO: implement isConnected
    return internetConnection.hasInternetAccess;
  }
}

RepositoryImpl -

class AuthRepositoryImpl implements AuthRepository {
  final AuthRemoteDatasource authRemoteDatasource;
  final NetworkInfo networkInfo;

  AuthRepositoryImpl({
    required this.authRemoteDatasource,
    required this.networkInfo,
    required this.crashLog,
  });

  @override
  ResultFuture<User> emailPasswordLogin({
    required String email,
    required String password,
  }) async {
    // TODO: implement emailPasswordLogin
    try {
      if (!await networkInfo.isConnected()) {
        return const Result.error(NoInternetFailure());
      }

      var user = await authRemoteDatasource.emailPasswordLogin(
        email: email,
        password: password,
      );

      return Result.success(user);
    } on AuthException {
      return const Result.error(AuthFailure());
    } catch (exception, stack) {
      return Result.error(UnknownFailure());
    }
  }
}

Solution

  • maybe something like this:

    class NetworkInfoImpl implements NetworkInfo {
          InternetConnection internetConnection;
        
          Stream<bool> get onConnectionChanged => _connectionChangedController.stream;
        
          final StreamController<bool> _connectionChangedController =
              StreamController<bool>.broadcast();
        
          NetworkInfoImpl({
            required this.internetConnection,
          });
        
          @override
          Future<bool> isConnected() {
            //check if has internet connection
            var hasInternet = internetConnection.hasInternetAccess;
            // Add a logic to check connection based on your
            //...
        
            //trigger the listeners;
            _connectionChangedController.add(hasInternet);
        
            return hasInternet;
          }
        }
    

    And a Cubit to listen to these changes:

     class ConnectivityCubit extends Cubit<bool> {
          ConnectivityCubit(this._repository) : super(false) {
            _repository.onConnectionChanged.listen((hasConnection) {
              //emit new states according to the internet connection
              emit(hasConnection);
            });
          }
          final NetworkInfoImpl _repository;
       }