Ad

How To Socket A AsBroadcastStream So That It Can Be Used In A Stream Builder?

- 1 answer

Hello i ran into a problem on Streams, specifically on how to use a broadcast stream for socket programming. Here is the code:

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'dart:typed_data';
import 'package:tcp/othermessage.dart';
import 'package:tcp/ownmessage.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';

void main() async {
  final socket =
      await Socket.connect('0.0.0.0', 3389); //This ip wouldn't work but I change it for safety reasons
  print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');
  runApp(MyApp(socket: socket));
  socket.write("h");
}

class MyApp extends StatelessWidget {
  final Socket socket;

  const MyApp({required this.socket, Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page', socket: socket),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final Socket socket;

  MyHomePage({Key? key, required this.title, required this.socket})
      : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final inputController = TextEditingController();

  ScrollController scrollcontrol = ScrollController();

  List<String> messageList = [];

  @override
  void dispose() {
    inputController.dispose();
    widget.socket.destroy();
    widget.socket.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: const Color.fromRGBO(236, 236, 236, 1),
        body: SafeArea(
          child: Column(
            children: <Widget>[
              StreamBuilder(
                  stream: widget.socket,
                  builder: (context, snapshot) {
                    if (snapshot.hasData == false ||
                        String.fromCharCodes(snapshot.data as Uint8List)
                                .contains("joined Connected to the server!") ==
                            true) {
                      return Container(
                          height: MediaQuery.of(context).size.height - 300);
                    }
                    String sent =
                        String.fromCharCodes(snapshot.data as Uint8List);
                    messageList.add(sent);
                    return Container(
                        color: const Color.fromRGBO(236, 235, 236, 100),
                        height: MediaQuery.of(context).size.height - 300,
                        child: ListView.builder(
                            controller: scrollcontrol,
                            shrinkWrap: true,
                            itemCount: messageList.length,
                            itemBuilder: (BuildContext context, int index) {
                              String messagerecieved = messageList[index];
                              List<String> messagedisected =
                                  messagerecieved.split(" ");
                              if (messagedisected[0] != "h:" &&
                                  messagerecieved.contains(
                                          "joined Connected to the server!") ==
                                      false) {
                                return OtherMessage(
                                    message: messageList[index]);
                              } else {
                                return OwnMessage(message: messageList[index]);
                              }
                            }));
                  }),
              Row(
                children: [
                  Container(
                    margin: EdgeInsets.only(left: 12),
                    width: 330,
                    decoration: BoxDecoration(
                        color: Color.fromRGBO(214, 214, 214, 100),
                        borderRadius: BorderRadius.circular(14.65)),
                    child: TextFormField(
                      keyboardType: TextInputType.multiline,
                      minLines: 1,
                      maxLines: 5,
                      decoration: const InputDecoration(
                          hintText: 'Enter your message',
                          border: InputBorder.none,
                          focusedBorder: InputBorder.none,
                          enabledBorder: InputBorder.none,
                          errorBorder: InputBorder.none,
                          disabledBorder: InputBorder.none,
                          contentPadding: EdgeInsets.only(
                              left: 15, bottom: 11, top: 11, right: 15)),
                      controller: inputController,
                    ),
                  ),
                  IconButton(
                      padding:
                          const EdgeInsets.only(left: 10, right: 12, top: 10),
                      iconSize: 50,
                      onPressed: () {
                        if (messageList.isNotEmpty) {
                          scrollcontrol.animateTo(
                              scrollcontrol.position.maxScrollExtent,
                              duration: const Duration(milliseconds: 100),
                              curve: Curves.easeOut);
                        }
                        String message = inputController.text;
                        widget.socket.write("h: " + message);
                        inputController.clear();
                      },
                      icon: SvgPicture.asset('assets/images/SendButton.svg'))
                ],
              ),
            ],
          ),
        ));
  }
}

I want to be able to expose the socket as a broadcastStream, I already tried using the asBroadcastStream function but I don't know how to pass it to another StreamBuilder. My plan is to be able to read status sent by the tcp server and update my AppBar title with StreamBuilder like so

AppBar(title: StreamBuilder<Object>(
    stream: widget.socket,
    builder: (context, snapshot) {
      return mycustomwidget();
    }
  )

As we know doing this is not possible cause the stream is not a broadcast stream and has already been listened by another streambuilder, I tried using asBroadCastStream like so

class _MyHomePageState extends State<MyHomePage> {
  final inputController = TextEditingController();

  ScrollController scrollcontrol = ScrollController();

  List<String> messageList = [];

   Stream mystream=widget.socket.asBroadcastStream();
 
  @override
  void dispose() {
    inputController.dispose();
    widget.socket.destroy();
    widget.socket.close();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    mystream.listen((value)=>print(value));

    return Scaffold(//...continuation

But obviously it comes back with a badState again. I'm still very new in handling streams like this I hope someone can clarify and fix my problem. Thank you!

Ad

Answer

Hello after a ripping my head off, it turns out you could do it with the asBroadcastStream function, the function yields an error before because I kept on using widget.socket in the onDestroy and in the other streambuilder instead of passing it to a new stream and then using that for other streambuidlers.

class _MyHomePageState extends State<MyHomePage> {
  final inputController = TextEditingController();

  ScrollController scrollcontrol = ScrollController();

  List<String> messageList = [];

  late Stream broadcaststream;

  @override
  void initState() {
    // TODO: implement initState
    broadcaststream = widget.socket.asBroadcastStream();
    super.initState();
  }

  @override
  void dispose() {
    inputController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: StreamBuilder(
                stream: broadcaststream,
                builder: (context, snapshot) {
                  if (snapshot.hasData == false) {
                    return (Text("Connecting"));
                  }
                  return (Text(
                      String.fromCharCodes(snapshot.data as Uint8List)));
                })),
        backgroundColor: Colors.white,
        body: SafeArea(
          child: SingleChildScrollView(
            reverse: true,
            child: Column(
              children: <Widget>[
                StreamBuilder(
                    stream: broadcaststream,
                    builder: (context, snapshot) {
                      if (snapshot.hasData == false ||
                          String.fromCharCodes(snapshot.data as Uint8List)
                                  .contains("Connected to the server!") ==
                              true) {
                        return Container(
                            height: MediaQuery.of(context).size.height - 300);
                      }
                      String sent =
                          String.fromCharCodes(snapshot.data as Uint8List);
                      messageList.add(sent);
                      return Container(
                          color: const Color.fromRGBO(236, 235, 236, 100),
                          height: MediaQuery.of(context).size.height - 300,
                          child: ListView.builder(
                              controller: scrollcontrol,
                              shrinkWrap: true,
                              itemCount: messageList.length,
                              itemBuilder: (BuildContext context, int index) {
                                String messagerecieved = messageList[index];
                                List<String> messagedisected =
                                    messagerecieved.split(" ");
                                if (messagedisected[0] != "${widget.title}:" &&
                                    messagerecieved.contains(
                                            "Connected to the server") ==
                                        false) {
                                  print(messagedisected[0]);
                                  return OtherMessage(
                                      message: messageList[index]);
                                } else {
                                  return OwnMessage(
                                      message: messageList[index]);
                                }
                              }));
                    }),
                Row(
                  children: [
                    Container(
                      margin: EdgeInsets.only(left: 12),
                      width: 330,
                      decoration: BoxDecoration(
                          color: Color.fromRGBO(214, 214, 214, 100),
                          borderRadius: BorderRadius.circular(14.65)),
                      child: TextFormField(
                        keyboardType: TextInputType.multiline,
                        minLines: 1,
                        maxLines: 5,
                        decoration: const InputDecoration(
                            hintText: 'Enter your message',
                            border: InputBorder.none,
                            focusedBorder: InputBorder.none,
                            enabledBorder: InputBorder.none,
                            errorBorder: InputBorder.none,
                            disabledBorder: InputBorder.none,
                            contentPadding: EdgeInsets.only(
                                left: 15, bottom: 11, top: 11, right: 15)),
                        controller: inputController,
                      ),
                    ),
                    IconButton(
                        padding:
                            const EdgeInsets.only(left: 10, right: 12, top: 10),
                        iconSize: 50,
                        onPressed: () {
                          if (messageList.isNotEmpty) {
                            scrollcontrol.animateTo(
                                scrollcontrol.position.maxScrollExtent,
                                duration: const Duration(milliseconds: 100),
                                curve: Curves.easeOut);
                          }
                          String message = inputController.text;
                          widget.socket.write("${widget.title}: " + message);
                          inputController.clear();
                        },
                        icon: SvgPicture.asset('assets/images/SendButton.svg'))
                  ],
                ),
              ],
            ),
          ),
        ));
  }
}``
Ad
source: stackoverflow.com
Ad