WebSockets в Flutter

WebSockets в Flutter

FlutterPulse

Эта статья переведена специально для канала FlutterPulse. В этом канале вы найдёте много интересных вещей, связанных с Flutter. Не забывайте подписываться! 🚀

Помимо установления соединений с серверами с помощью обычных HTTP-запросов, вы также можете использовать WebSockets. WebSockets позволяют иметь двустороннюю (двухстороннюю) связь с сервером без опроса. Поэтому использование WebSockets в Flutter позволит вам создавать интерактивные и отзывчивые приложения, которые могут обрабатывать обновления данных в реальном времени.

WebSockets vs HTTP

Как упоминалось выше, обе эти технологии могут использоваться для связи с сервером. Но хотя обе стремятся доставлять актуальную информацию, они значительно отличаются следующими способами.

Модель соединения:
WebSockets устанавливают постоянное и непрерывное двустороннее соединение между клиентом и сервером. Таким образом, нет накладных расходов, связанных с повторным установлением новых соединений каждый раз.

HTTP-опрос основывается на модели запроса и ответа. То есть, клиент периодически отправляет запросы на сервер, чтобы проверять и получать обновления.

Задержка:
Из-за того, что WebSockets поддерживают постоянное соединение между клиентом и сервером, задержка минимальна. Постоянный HTTP-запрос-ответ вносит задержку.

Использование данных:
WebSockets потребляют меньше ресурсов и более эффективны при обработке больших объемов данных. С HTTP использование данных выше, так как частые запросы создают значительную нагрузку на сервер.

Сложность:
HTTP проще реализовать на базовом уровне по сравнению с WebSockets, которые требуют поддержки на стороне сервера.

WebSockets революционизировали веб, превратив неудобные, медленные взаимодействия в реальном времени в плавные, низкозадержевые опыты, сделав их основным выбором для динамичных, дружелюбных к пользователю приложений.

Реализация

Для этой демонстрации мы будем использовать эхо-WebSocket. Это сервер, который просто возвращает (или отражает) любое полученное сообщение. Клиент (мы) отправит сообщение на сервер, и сервер немедленно вернет то же сообщение. Таким образом, он используется в основном для тестирования и отладки. Например, wss://ws.postman-echo.com/raw или ws://echo.websocket.org

Начнем с реализации WebSocket в Flutter. Добавьте последний пакет web_socket_channel в зависимости и не забудьте запустить flutter pub get для его установки.

dependencies:
  flutter:
    sdk: flutter
  web_socket_channel: ^3.0.2

В вашем файле Dart добавьте импорт пакета в начало: import 'package:web_socket_channel/io.dart'; и продолжайте инициализировать канал WebSocket вместе с другими переменными — TextEditingController для обработки ввода клиента в TextField и List для хранения отправленных и полученных сообщений.

final channel = IOWebSocketChannel.connect('wss://ws.postman-echo.com/raw');
final TextEditingController _controller = TextEditingController();
final List<String> _messages = [];

В функции initState() которая выполняется при первом создании виджета, мы будем слушать входящие сообщения WebSocket и обновлять список _messages с помощью setState() чтобы интерфейс отражал изменения. Вы также можете обрабатывать ошибки канала здесь.

@override
  void initState() {
    super.initState();
    channel.stream.listen(
      (message) {
        setState(() {
          _messages.add('[recv]: $message');
        });
      },
      onError: (error) {
        print('WebSocket Error: $error');
      },
      onDone: () {
        print('WebSocket Closed');
      },
    );
  }

Интерфейс будет в основном состоять из двух частей:
ListView для отображения отправленных и полученных сообщений,
Row с TextFormField для ввода пользователем фактических сообщений, которые будут отправлены на сервер, и IconButton для вызова функции _sendMessage.

...
Column(
    children: [
      Expanded(
        child: ListView.builder(
          itemCount: _messages.length,
          itemBuilder: (context, index) {
            return ListTile(title: Text(_messages[index])); // отображает отправленные и полученные сообщения
          },
        ),
      ),
      Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.black12),
          borderRadius: BorderRadius.only(
            topRight: Radius.circular(10),
            topLeft: Radius.circular(10),
          ),
        ),
        child: Row(
          children: [
            Expanded(
              child: Padding(
                padding: EdgeInsets.fromLTRB(10, 0, 0, 10),
                child: TextFormField(
                  controller: _controller,
                  maxLines: 1,
                  style: TextStyle(fontSize: 14),
                  decoration: InputDecoration(
                    hintText: 'Отправить сообщение для эха...',
                    border: InputBorder.none,
                  ),
                ),
              ),
            ),
            IconButton(
                onPressed: _sendMessage, // функция для отправки сообщения на сервер
                icon: Icon(Icons.send),
              ),
          ],
        ),
      ),
    ],
  ),
...

Функция _sendMessage начинается с проверки, что поле ввода не пустое. Если оно не пустое, мы сохраняем сообщение в списке, чтобы оно появилось в чате, а затем отправляем сообщение на сервер через channel.sink.add(). В конце мы просто очищаем поле ввода.

void _sendMessage() {
  if (_controller.text.isNotEmpty) {
    String text = _controller.text;
    setState(() {
      _messages.add('[send]: $text');
    });
    channel.sink.add(text);
    _controller.clear();
  }
}

Как всегда, не забудьте закрыть каналы и освободить контроллеры, чтобы избежать утечек памяти.

  @override
  void dispose() {
    channel.sink.close();
    _controller.dispose();
    super.dispose();
  }

Вот как это будет работать.

Полный код этой реализации можно найти в моем репозитории здесь. Проверьте и поделитесь своими мыслями.

"Когда вы можете связаться с живой аудиторией и получаете мгновенный отклик, это просто великолепно."
— Limahl

Спасибо за чтение ❤

Ссылки1. https://docs.flutter.dev/cookbook/networking/web-sockets
2.
https://websocket.org/
3.
https://www.videosdk.live/developer-hub/websocket/flutter-websockets

Report Page