如何套接 asBroadcastStream 以便它可以在流生成器中使用?
How to socket a asBroadcastStream so that it can be used in a stream builder?
你好我 运行 遇到一个关于 Streams 的问题,特别是关于如何使用广播流进行套接字编程。这是代码:
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'))
],
),
],
),
));
}
}
我希望能够将套接字公开为广播流,我已经尝试使用 asBroadcastStream 函数,但我不知道如何将它传递给另一个 StreamBuilder。我的计划是能够读取 tcp 服务器发送的状态并使用 StreamBuilder 更新我的 AppBar 标题
AppBar(title: StreamBuilder<Object>(
stream: widget.socket,
builder: (context, snapshot) {
return mycustomwidget();
}
)
我们知道这样做是不可能的,因为流不是广播流并且已经被另一个流生成器收听,我尝试像这样使用 asBroadCastStream
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
但显然它又返回了一个 badState。我在处理这样的流方面仍然很陌生,我希望有人能澄清并解决我的问题。谢谢!
你好,把我的脑袋扯下来后,原来你可以用 asBroadcastStream 函数来做,这个函数之前会产生错误,因为我一直在 onDestroy 和另一个 streambuilder 中使用 widget.socket将其传递给新流,然后将其用于其他流构建器。
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'))
],
),
],
),
),
));
}
}``
你好我 运行 遇到一个关于 Streams 的问题,特别是关于如何使用广播流进行套接字编程。这是代码:
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'))
],
),
],
),
));
}
}
我希望能够将套接字公开为广播流,我已经尝试使用 asBroadcastStream 函数,但我不知道如何将它传递给另一个 StreamBuilder。我的计划是能够读取 tcp 服务器发送的状态并使用 StreamBuilder 更新我的 AppBar 标题
AppBar(title: StreamBuilder<Object>(
stream: widget.socket,
builder: (context, snapshot) {
return mycustomwidget();
}
)
我们知道这样做是不可能的,因为流不是广播流并且已经被另一个流生成器收听,我尝试像这样使用 asBroadCastStream
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
但显然它又返回了一个 badState。我在处理这样的流方面仍然很陌生,我希望有人能澄清并解决我的问题。谢谢!
你好,把我的脑袋扯下来后,原来你可以用 asBroadcastStream 函数来做,这个函数之前会产生错误,因为我一直在 onDestroy 和另一个 streambuilder 中使用 widget.socket将其传递给新流,然后将其用于其他流构建器。
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'))
],
),
],
),
),
));
}
}``