DEV Community

Musab
Musab

Posted on

How to use Flutter Riverpod with Socket.io

Hi Everyone
in this small article I'll show you to use socket.io with flutter riverpod

I'm assuming you already have basic knowledge about flutter riverpod and socketio

*first we will make node socket io server code *

1- make new folder name it as you like
2- run npm init -y
3- make file named server.js

paste the following code

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

//Whenever someone connects this gets executed
io.on('connection', function (socket) {

    console.log('A user connected');

    //Whenever someone disconnects this piece of code executed
    socket.on('disconnect', function () {
        console.log('A user disconnected');
    });

    socket.on('message', function (data) {
        // when server receives event called message
        // it convert the mesage to upper case
        // then split it to array
        var newMessage = [...data.toUpperCase()];
        console.log(newMessage);
        socket.emit('broadcast', newMessage);
    })
});

// i'm exposing to to my wifi ip because i'm debugging using adb
http.listen(3000, '192.168.62.123', function () {
    // to work locally use the followning line 
// http.listen(3000,  function () {

    console.log('listening on *:3000');
});
Enter fullscreen mode Exit fullscreen mode

then in terminal run node server.js

secondly we'll work on flutter application

1- create new flutter project
'flutter create my_project_name'
2- install packages , paste in pubsec.yaml
socket_io_client: *
flutter_riverpod: *

create class SocketService

class SocketService {
  IO.Socket socket = IO.io(
      // im using adb so i need to use my wifi ip
      'http://192.168.62.123:3000',
      IO.OptionBuilder()
          .setTransports(['websocket']) // for Flutter or Dart VM
          .disableAutoConnect() // disable auto-connection
          // .setExtraHeaders({'foo': 'bar'}) // optional
          .build());

  initConnection() {
    socket.connect();
    socket.on('connection', (_) {
      log('connect ${_.toString()}');
    });
    log('Trying Connection');
    socket.onConnect((_) {
      log('connect');
    });

    socket.onerror((_) {
      log('Error Is ${_.toString()}');
    });
  }

  sendMessage(message) {
    socket.emit('message', message);
  }
}
Enter fullscreen mode Exit fullscreen mode

call the initConnection function on main

void main() {
  // call initial connection in the main
  // assuming you want the connection to be continuous
  SocketService().initConnection();
}
Enter fullscreen mode Exit fullscreen mode

create ConsumerWidget

class StreamProviderWithConsumer extends ConsumerWidget {
  const StreamProviderWithConsumer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {

    return Scaffold(appBar: AppBar(), body: Center());
  }
}
Enter fullscreen mode Exit fullscreen mode

add stream provider

final providerOfSocket = StreamProvider.autoDispose((ref) async* {
  StreamController stream = StreamController();

  SocketService().socket.onerror((err) => log(err));
  SocketService().socket.onDisconnect((_) => log('disconnect'));
  SocketService().socket.on('fromServer', (_) => log(_));

  SocketService().socket.on('broadcast', (data) {
    stream.add(data);

    log(data.toString());
  });

  SocketService().socket.onerror((_) {
    log("Error IS ${_.toString()}");
  });

  /** if you using .autDisopose */
  // ref.onDispose(() {
  //   // close socketio
  //   _stream.close();
  //   SocketService().socket.dispose();
  // });

  await for (final value in stream.stream) {
    log('stream value => ${value.toString()}');
    yield value;
  }
});

Enter fullscreen mode Exit fullscreen mode

watch stream provider inside the consumer widget
final message = ref.watch(providerOfSocket);

add next line

   Center(
              child: message.when(
                  data: (data) {
                    return Text(data.toString());
                  },
                  error: (_, __) {
                    log(_.toString());
                    return const Text('Error');
                  },
                  loading: () => const Text('Loading ')),
            )
Enter fullscreen mode Exit fullscreen mode

now when there 'broadcast' event fired , you'll The text will change

next I'll add TextEditingController and TextField
so i can send any string it will be processed and return back to me

the full
consumer widget code will be

class StreamProviderWithConsumer extends ConsumerWidget {
  const StreamProviderWithConsumer({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    TextEditingController _controller = TextEditingController();
    final message = ref.watch(providerOfSocket);

    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: Column(
          children: [
            SizedBox(
              height: 50,
              width: 250,
              child: TextField(
                controller: _controller,
              ),
            ),
            ElevatedButton(
                onPressed: () => SocketService().sendMessage(_controller.text),
                child: const Text('Send Message')),
            const Divider(),
            Center(
              child: message.when(
                  data: (data) {
                    return Text(data.toString());
                  },
                  error: (_, __) {
                    log(_.toString());
                    return const Text('Error');
                  },
                  loading: () => const Text('Loading ')),
            )
          ],
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

see the full code

Top comments (0)