Flutter WebSocket

Flutter WebSocket

WebSocket adalah salah satu cara untuk terhubung ke server, seperti halnya paket http. Namun, WebSocket memungkinkan komunikasi dua arah dengan server tanpa perlu melakukan polling.

Dalam artikel ini, kita akan membahas topik terkait penggunaan WebSocket di Flutter, antara lain:

  1. Cara terhubung ke server WebSocket
  2. Cara mendengarkan pesan dari server
  3. Cara mengirim data ke server
  4. Cara menutup koneksi WebSocket

Sebagai contoh, dalam artikel ini kita akan menggunakan server uji yang disediakan oleh piesocket.com.

Menghubungkan ke Server WebSocket

Paket web_socket_channel memiliki fungsi yang diperlukan untuk terhubung ke server WebSocket. Paket ini menyediakan WebSocketChannel yang memungkinkan pengguna untuk mendengarkan pesan dari server dan mengirimkan pesan ke server.

Di Flutter, gunakan baris kode berikut untuk membuat WebSocketChannel yang terhubung ke server:

final channel = IOWebSocketChannel.connect('wss://demo.piesocket.com/v3/channel_123?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self');

Mendengarkan Pesan dari Server

Sekarang setelah kita berhasil menghubungkan ke server, kita akan mengirimkan pesan ke server dan mendapatkan pesan yang sama sebagai balasan:

StreamBuilder(
  stream: widget.channel.stream,
  builder: (context, snapshot) {
    return Text(snapshot.hasData ? '${snapshot.data}' : '');
  },
);

Mengirim Data ke Server

Untuk mengirim data ke server, tambahkan pesan add() ke sink yang disediakan oleh WebSocketChannel seperti yang ditunjukkan di bawah ini:

channel.sink.add('Hello Guys!');

Menutup Koneksi

Untuk menutup koneksi ke WebSocket, gunakan yang berikut:

channel.sink.close();

Contoh:

Untuk mengikuti contoh di bawah ini Anda harus menambahkan dependency http di pubspec.yaml

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

Future fetchAlbum() async {
  final response = await http
      .get(Uri.parse('https://jsonplaceholder.typicode.com/albums/1'));

  if (response.statusCode == 200) {
    return Album.fromJson(json.decode(response.body));
  } else {
    throw Exception('Loading album failed!');
  }
}

Future updateAlbum(String title) async {
  final http.Response response = await http.put(
    Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
    body: jsonEncode(<String, String>{
      'title': title,
    }),
  );

  if (response.statusCode == 200) {
    return Album.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed to update the album!');
  }
}

class Album {
  final int id;
  final String title;

  Album({required this.id, required this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      id: json['id'],
      title: json['title'],
    );
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State {
  final TextEditingController _controller = TextEditingController();
  late Future _futureAlbum;

  @override
  void initState() {
    super.initState();
    _futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Update Data',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Nextgen Tutorial'),
          backgroundColor: Colors.blue,
        ),
        body: Container(
          alignment: Alignment.center,
          padding: const EdgeInsets.all(8.0),
          child: FutureBuilder(
            future: _futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasData) {
                  return Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Text('Judul Album Saat ini'),
                      const SizedBox(
                        height: 18,
                      ),
                      Text(snapshot.data?.title ?? 'null'),
                      TextField(
                        controller: _controller,
                        decoration: const InputDecoration(
                            hintText: 'Masukkan judul album yang diinginkan'),
                      ),
                      ElevatedButton(
                        child: const Text('Update Data'),
                        onPressed: () {
                          setState(() {
                            _futureAlbum = updateAlbum(_controller.text);
                            _controller.text = '';
                          });
                        },
                      ),
                    ],
                  );
                } else if (snapshot.hasError) {
                  return Text("${snapshot.error}");
                }
              }
              return const CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

Output:

Tinggalkan Balasan

Keranjang Belanja0
Keranjang belanja kosong ...
0