How to manage network state with BLOC properly

Reading time: 2 minutes

It’s always a good idea to handle the network state in an application that uses any backend service. It can be just a notification, or even switching to “offline mode”.

This is the result we are looking for.

We have application in offline mode, then turn on Wi-Fi and see mode changed to online.

Let’s get connectivity package first:

connectivity: ^0.4.9+3

In our example widget, we create the corresponding ConnectivityBloc, add the first event at widget start, and build a proper Text widget based on the current state.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_examples/example/bloc_connectivity/connectivity_bloc.dart';

class ConnectivityExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: BlocProvider(
            create: (context) => ConnectivityBloc()..add(AppStartedEvent()),
            child: _buildStatePage(context)));
  }

  Widget _buildStatePage(BuildContext context) {
    return Center(child: BlocBuilder<ConnectivityBloc, ConnectivityState>(
        builder: (context, state) {
      if (state is OnlineState)
        return Text("We are online");
      else
        return Text("We are offline");
    }));
  }
}

NetworkUtils class helps to check if we are online or not.

import 'package:connectivity/connectivity.dart';

class NetworkUtils {
  static Future<bool> isOnline() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile)
      return true;
    else if (connectivityResult == ConnectivityResult.wifi)
      return true;
    else
      return false;
  }
}

And finally our BLOC architecture class. There is nothing special in states or events, it should be self-explanatory. When an application starts we check the network state first time and create a Connectivity class and assign a listener that will add a proper event if the network state will change.

import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:connectivity/connectivity.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_examples/example/utils/network_utils.dart';

part 'connectivity_event.dart';

part 'connectivity_state.dart';

class ConnectivityBloc extends Bloc<ConnectivityEvent, ConnectivityState> {
  var subscription;

  ConnectivityBloc() : super(OfflineState());

  @override
  Stream<ConnectivityState> mapEventToState(
    ConnectivityEvent event,
  ) async* {
    if (event is AppStartedEvent) yield* _startApp();
    if (event is OfflineEvent) yield OfflineState();
    if (event is OnlineEvent) yield OnlineState();
  }

  Stream<ConnectivityState> _startApp() async* {
    _startNetworkListener();
    yield OfflineState();
    if (await NetworkUtils.isOnline()) yield OnlineState();
  }

  _startNetworkListener() {
    subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      if (result == ConnectivityResult.none)
        add(OfflineEvent());
      else
        add(OnlineEvent());
    });
  }

  @override
  Future<Function> close() {
    subscription.cancel();
    return super.close();
  }
}

//State
part of 'connectivity_bloc.dart';

abstract class ConnectivityState extends Equatable {
  const ConnectivityState();
}

class OfflineState extends ConnectivityState {
  const OfflineState();

  @override
  String toString() => 'OfflineState';

  @override
  List<Object> get props => [];
}

class OnlineState extends ConnectivityState {
  const OnlineState();

  @override
  String toString() => 'OnlineState';

  @override
  List<Object> get props => [];
}

//Event
part of 'connectivity_bloc.dart';

abstract class ConnectivityEvent extends Equatable {
  const ConnectivityEvent();
}

class AppStartedEvent extends ConnectivityEvent {
  @override
  String toString() => 'AppStartedEvent';

  @override
  List<Object> get props => [];
}

class OnlineEvent extends ConnectivityEvent {
  @override
  String toString() => 'NetworkOnline';

  @override
  List<Object> get props => [];
}

class OfflineEvent extends ConnectivityEvent {
  @override
  String toString() => 'NetworkOnline';

  @override
  List<Object> get props => [];
}

Leave a Reply

Your email address will not be published. Required fields are marked *