Unk*_*now 5 future http stream flutter stream-builder
我正在尝试使用 Flutter 制作我的第一个社交应用程序,但我陷入了困境。我想从我的 api 获取我的消息(在两个用户之间的对话中)。当我使用 Future 和 Future Builder 时这不是问题,但我希望在发送新消息时更新消息列表!
我发现我们可以用流来实现它,但每次我尝试将我的 Future In Stream 转换时,它仍然有效,但就像它是一个 Future (它永远不会更新新消息)。
这里是我的代码的简化部分:
class Test extends StatelessWidget {
final Conv conv;
final User otherUser;
const Test({Key key, this.conv, this.otherUser}) : super(key: key);
Stream<List<Message>> messageFlow(String convId) {
return Stream.fromFuture(getMessages(convId));
}
Future<List<Message>> getMessages(String convId) async {
var data = await http
.post(MyApiUrl, headers: <String, String>{}, body: <String, String>{
"someParam": "param",
"id": convId,
});
var jsonData = json.decode(data.body);
List<Message> messages = [];
for (var m in jsonData) {
Message message = Message.fromJson(m);
messages.add(message);
}
return messages;
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: messageFlow(conv.id),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading'),
),
);
}
return ListView.builder(
reverse: true,
controller: _messagesListController,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Message message = snapshot.data[index];
var isMe = message.owner == otherUser.id ? false : true;
return _buildMessage(message, isMe);
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
如果你能帮助我那就太好了!
我无法复制您的示例代码,但这里是我如何理解您的问题。
我们首先定义Future和 的区别Streams:
Future就像你点外卖时他们给你的带有数字的代币;您提出了请求,但结果尚未准备好,但您有一个占位符。当结果准备好时,您会收到回调(外卖柜台上方的数字板显示您的号码,或者他们大声喊出) - 您现在可以进去拿食物(结果)外卖。
一条溪流就像那条带着小寿司碗的腰带。坐在那张桌子旁,您就已经“订阅”了该流。您不知道下一艘寿司船何时到达 - 但当厨师(消息源)将其放入流(传送带)中时,订阅者就会收到它。需要注意的重要一点是,它们是异步到达的(你不知道下一艘船/消息何时到达),但它们会按顺序到达(即,如果厨师按某种顺序将三种类型的寿司放在传送带上——您会看到它们以相同的顺序出现)
现在,这是一个如何从头开始创建自己的流的示例:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 1st approach
final StreamController _streamController = StreamController();
addData()async{
for(int i = 1; i<= 10; i++) {
await Future.delayed(Duration(seconds: 1));
_streamController.sink.add(i);
}
}
// 2nd approach
// This approach will prevent some approach of memory leaks
Stream<int> numberStream() async*{
for(int i = 1; i<= 10; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_streamController.close();
}
@override
void initState() {
// TODO: implement initState
super.initState();
addData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Stream"),
),
body: Center(
child: StreamBuilder(
stream: numberStream().map((number) => "number $number"),
builder: (context, snapshot){
if(snapshot.hasError)
return Text("hey there is some error");
else if (snapshot.connectionState == ConnectionState.waiting)
return CircularProgressIndicator();
return Text("${snapshot.data}", style: Theme.of(context).textTheme.display1,);
},
)
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以查看此 SO 帖子以获取一些参考。
在这里,我调整了上面 SO 帖子中的示例,以创建一个迷你简单的聊天服务器来显示消息如何更新。
import 'dart:async';
import 'package:flutter/material.dart';
class Server {
StreamController<String> _controller = new StreamController.broadcast();
void simulateMessage(String message) {
_controller.add(message);
}
Stream get messages => _controller.stream;
}
final server = new Server();
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => new _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<String> _messages = <String>[];
StreamSubscription<String> _subscription;
@override
void initState() {
_subscription = server.messages.listen((message) async => setState(() {
_messages.add(message);
}));
super.initState();
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
TextStyle textStyle = Theme.of(context).textTheme.display2;
return new Scaffold(
appBar: new AppBar(
title: new Text('Sample App'),
),
body: new ListView(
children: _messages.map((String message) {
return new Card(
child: new Container(
height: 100.0,
child: new Center(
child: new Text(message, style: textStyle),
),
),
);
}).toList(),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
new FloatingActionButton(
child: new Icon(Icons.account_circle_outlined),
onPressed: () {
// simulate a message arriving
server.simulateMessage('Hello World');
},
),
SizedBox(
height: 20.0,
),
new FloatingActionButton(
child: new Icon(Icons.account_circle_rounded),
onPressed: () {
// simulate a message arriving
server.simulateMessage('Hi Flutter');
},
),
],
),
);
}
}
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomeScreen(),
);
}
}
void main() {
runApp(new SampleApp());
}
Run Code Online (Sandbox Code Playgroud)
这里有一些教程可供更好的参考:
| 归档时间: |
|
| 查看次数: |
13179 次 |
| 最近记录: |