Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter design pattern for offline / online web socket sync

Tags:

flutter

dart

Relatively new to flutter development, but understand the basics. Looking to build a slightly more complex app at the moment that needs to operate while offline and then sync back to a server side when back on-line. However, when on-line, needs to have content on the screens constantly kept up-to-date based on back-end changes.

Conceptually, something like this: enter image description here

Example flow as follows:

  1. User loads the app and app synchronizes its database with the server
  2. User navigates to Screen 1 and sees the relevant information from the synchronized local database
  3. User makes a change to data on-screen. This data is saved in the database and then notified to the Server.
  4. A different user makes a change (on a different app to the backend data). The server notifies clients of the change. Screen 1 is automatically updated to reflect the new data.
  5. User looses network connectivity, but can continue operating on the data with changes being saved locally
  6. Network connectivity is restored and changes made locally are synchronized with the server.

Naturally, there will be some complexity in the synchronisation aspects of the data in a multi-user environment. However, I am less concerned with this and more interested in the best techniques or libraries to utilize to achieve the requirement.

I get that connecting to a websocket backend is pretty straight forward. Equally, there are many databases that appear to be good options that I could use. I am also sure that operating in offline and synchronising with the back-end when back online is a pretty common requirement (albeit that its not something I know anything about from a Flutter perspective).

Would appreciate any advise or guidance on the correct design pattern to use and/or tooling / libraries / techniques. Objective here is obviously to save me re-inventing the wheel as I am sure many of you have done similar things and have good recommendations from experience!

Thanks Jab

like image 510
Jablalr Avatar asked Sep 18 '25 02:09

Jablalr


1 Answers

firstly i would appreciate the way you described you concern in that detailed way.

Packages required to be added in pubspec.yaml file:

  • socket_io_client: ^0.9.4
  • connectivity: ^3.0.6
  • shared_preferences: ^0.5.8

shared_preferences

it will be used to to store data in offline mode. for good understanding lets see a use case i.e.

  1. user did some changes in offline mode and exits the app before connection is restored in that case added data could lost.
  2. user did some change lets assume user added item in offline and if user added again second item before connection is restored previous added item or data may lost.

so to overcome these sort of conditions, would prefer to store data locally then ones connection is restored the data will sent to server.

connectivity package

we will use this package to check weather we are connected to internet.

socket_io_client

for making request to server we usually have two options one is this web socket and other is http request. in online mode we usually uses http request as it is less complex while implementing comparatively although websocket is used in online mode when we don't want to see loading or request hit time as websocket only connects to server one time after that can directly emit and fetch data from server.

working:- step 1 firtly check if we are online or offline if offline then store the data changed or added locally (if needed try to store data in list form and add each time the user adds data as item of list, later the whole list or array will send to server)

//checking for network
Future<bool> checkConnection() async{
  var connectivityResult = await(Connectivity().checkConnectivity());
  if (connectivityResult == ConnectivityResult.mobile) {
    return true;
  } else if (connectivityResult == ConnectivityResult.wifi) {
    return true;
  }
  return false;
}

if network status is false store data locally

List<String> listAdded = pref.getStringList("key") ?? [];
ticketCollectorObject.add(json.encode(newDataList));
pref.setStringList("key", listAdded);

step 2 send data to server now we have to connect websocket to backend and ones connection is established can emit or send data to socket.

using this can connect to web socket

void connectToServer() async {
try {
  String token = token;
  SharedPreferences pref = await SharedPreferences.getInstance();
  // Configure socket transports must be sepecified
  IO.Socket socket = IO.io(
      'http:// host url',
      OptionBuilder().setTransports(['websocket']) // for Flutter or Dart VM
          .setExtraHeaders({'token': token}) // optional
          .build());

      // Connect to websocket
      socket.connect();
      socket.onConnect((_) {
        print('connection successful with id: ${socket.id}');
        List<String> offlineData =
            pref.getStringList("key");
        List<Map<String, dynamic>> listObject = [];
        for (int i = 0; i < offlineData.length; i++) {
          listObject.add(jsonDecode(offlineData[i]));
        }
        String dataToSend = jsonEncode(listObject);
        print(dataToSend);
       //response from server will be printed
      socket.on(
        'response',
        (data) {
          print(data);
          if (data['message'] == "Success")
          //as data was sent successfully so have to clean locally stored data
            pref.setStringList("key", []);
        },
      );

      print("status of socket with server connedction : ${socket.connected}");
      socket.on('disconnect', (_) => print('disconnect'));
      socket.on('fromServer', (_) => print(_));
    } catch (e) {
      print(e.toString());
    }
  }

call this connectToServer() function in initstate((){}) of home page as well with the send button on the screen so that even if users closes the app or restart the app the data will be updated automatically

ones data is emited after success connection of socket with server the socket keep on trying to send data till requests hits successfully so in offline mode ones we call connectToServer() the data will be sent to server ones internet is restored without any user interaction automatically.

notes:

  • make surethe version of socket used backend and front part should be same.
  • server url should be "http " not "https".
like image 139
Tarun Jain Avatar answered Sep 19 '25 20:09

Tarun Jain