首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从websocket消息动态创建Widget -未处理异常:构造函数中调用的setState()

从websocket消息动态创建Widget -未处理异常:构造函数中调用的setState()
EN

Stack Overflow用户
提问于 2021-04-12 15:21:12
回答 1查看 410关注 0票数 0

当我从websocket接收数据时,我想动态地添加一个ListTile。当我将新数据添加到全局列表中时,ListView似乎还没有准备好。

我得到了这个错误

错误:setState/shell/ called /shell. in (242) Dart未处理异常:在构造函数中调用setState():_MyHomePageState#4c6c6(生命周期状态:已创建,没有小部件,未挂载)

处理此代码时发生错误。

代码语言:javascript
运行
复制
  void addItem(Item item) {
    setState(() {
      items.add(item);
    });
  }

我试图应用这些解决方案,但没有一个对我有效:

这是我的测试应用程序:

依赖关系

代码语言:javascript
运行
复制
dependencies:
  flutter:
    sdk: flutter
  web_socket_channel: ^2.0.0
  intl: ^0.17.0

main.dart

代码语言:javascript
运行
复制
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课程

代码语言:javascript
运行
复制
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;
    }
  }
}

还有我的物品课

代码语言:javascript
运行
复制
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'),
];

谢谢

EN

回答 1

Stack Overflow用户

发布于 2021-04-13 00:57:23

问题在于,您正在调用addItem,后者调用setState,但是调用它时还没有状态。

尝试将全局函数移动到state类并从initState调用它们

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67061071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档