Flutter - 从 websocket 消息动态创建小部件 - 未处理的异常:在构造函数中调用 setState()
Posted
技术标签:
【中文标题】Flutter - 从 websocket 消息动态创建小部件 - 未处理的异常:在构造函数中调用 setState()【英文标题】:Flutter - Create Widget dynamically from websocket message - Unhandled Exception: setState() called in constructor 【发布时间】:2021-07-07 16:37:50 【问题描述】:当我从 websocket 接收数据时,我想动态添加一个 ListTile。 当我将新数据添加到全局列表时,ListView 似乎还没有准备好。
我收到了这个错误
[ERROR:flutter/shell/common/shell.cc(242)] Dart 未处理异常:setState() 在构造函数中调用:_MyHomePageState#4c6c6(生命周期状态:已创建,无小部件,未安装)
处理这段代码时发生的错误
void addItem(Item item)
setState(()
items.add(item);
);
我尝试应用这些解决方案,但没有一个适合我:
Flutter Dart setState not working: Unhandled Exception: setState() called in constructor: ...(lifecycle state: created, no widget, not mounted) Flutter Unhandled Exception: setState() called in constructor:这是我的测试应用:
依赖
dependencies:
flutter:
sdk: flutter
web_socket_channel: ^2.0.0
intl: ^0.17.0
main.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:test_add_from_websocket/Item.dart';
import 'package:test_add_from_websocket/websocket.dart';
void main()
runApp(MyApp());
Future _init() async
final WebSocket _socket = WebSocket();
_socket.connect('wss://echo.websocket.org', connectionListener, messageListener);
void connectionListener(WebSocket socket, bool connected)
print('Status : ' + (connected ? 'Connected' : 'Failed to connect'));
void messageListener(WebSocket socket, String message)
print('websocket received: $message');
Map itemMap = jsonDecode(message);
var _item = Item.fromJson(itemMap);
MyHomePage().addItem(_item);
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FutureBuilder(
future: _init(),
builder: (context, snapshot)
if (snapshot.connectionState == ConnectionState.done)
return MyHomePage();
else
return Text('Loading');
,
),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
void addItem(Item item)
_MyHomePageState().addItem(item);
class _MyHomePageState extends State<MyHomePage>
void addItem(Item item)
setState(()
items.add(item);
);
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text('Add from websocket event'),
),
body: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index)
return ListTile(
leading: Icon(Icons.access_time),
title: Text(items[index].time),
);
),
floatingActionButton: FloatingActionButton(
onPressed: ()
DateTime now = DateTime.now();
Item _item = Item(
time: DateFormat.Hm().format(now),
);
print(_item.time);
final WebSocket _socket = WebSocket();
_socket.send(jsonEncode(_item));
,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
我的 WebSocket 类
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/status.dart' as status;
class WebSocket
static final WebSocket _instance = WebSocket._internal();
factory WebSocket() => _instance;
WebSocket._internal();
String _url;
bool _connected;
WebSocketChannel _channel;
connect(String url, Function connectionListener, Function messageListener)
try
_url = url;
_channel = IOWebSocketChannel.connect(_url);
_connected = true;
connectionListener(_instance, _connected);
print('websocket connected to $_url');
_channel.stream.listen(
(message)
print('websocket receive $message');
messageListener(_instance, message);
,
onDone: ()
_connected = false;
connectionListener(_instance, _connected);
print('websocket closed');
,
onError: (error)
print('websocket error $error');
,
);
catch (e)
print('websocket exception $e');
_connected = false;
connectionListener(_connected);
close()
if (_connected)
_channel.sink.close(status.normalClosure);
bool send(String message)
try
if (_channel == null) throw ('_channel undefined');
_channel.sink.add(message);
return true;
catch (e)
return false;
还有我的 Item 类
class Item
final String time;
Item(this.time);
Item.fromJson(Map<String, dynamic> json) : time = json['time'];
Map<String, dynamic> toJson() => 'time': time;
List<Item> items = [
Item(time: '10:22'),
Item(time: '11:22'),
];
谢谢
【问题讨论】:
【参考方案1】:问题是您正在调用 addItem
,而后者又调用了 setState
,但是当您调用它时还没有状态
尝试将您的全局函数移动到状态类并从 initState 调用它们
【讨论】:
以上是关于Flutter - 从 websocket 消息动态创建小部件 - 未处理的异常:在构造函数中调用 setState()的主要内容,如果未能解决你的问题,请参考以下文章
如何从 websocket 端点外部发出 websocket 消息?