Я хочу динамически добавлять ListTile, когда получаю данные из веб-сокета. ListView кажется не готовым, когда я добавляю новые данные в свой глобальный список.
Я получаю эту ошибку
[ОШИБКА: flutter / shell / common / shell.cc (242)] Необработанное исключение Dart: setState () вызывается в конструкторе: _MyHomePageState # 4c6c6 (состояние жизненного цикла: создано, нет виджета, не смонтировано)
Ошибка произошла при обработке этого кода
void addItem(Item item) {
setState(() {
items.add(item);
});
}
Я пытался применить эти решения, но у меня ничего не работает:
- Flutter Dart setState не работает: необработанное исключение: setState () вызывается в конструкторе: ... (состояние жизненного цикла: создано, нет виджета, не смонтировано)
- Необработанное исключение Flutter: setState () вызывается в конструкторе:
Вот мое тестовое приложение:
зависимости
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'),
];
Спасибо