简体   繁体   English

提供者:如何在 `StreamBuilder()` 中`notifyListener()`? 它会导致错误“setState() 或 markNeedsBuild() 在构建期间调用”

[英]Provider: How can I `notifyListener()` within a `StreamBuilder()`? It causes the error `setState() or markNeedsBuild() called during build`

I have a Provider model such as provider_model.dart :我有一个Provider模型,例如provider_model.dart

import 'package:flutter/material.dart';

class ProviderModel extends ChangeNotifier {
  final List<String> _myList = [];

  List<String> get myList => [..._myList];

  void addItem(String item) {
    _myList.add(item);
    notifyListeners();
  }
}

Now, Flutter documentation shows us how to listen to websockets .现在,Flutter 文档向我们展示了如何监听 websockets Here I am using their example together with my ProviderModel() :在这里,我将他们的示例与我的ProviderModel()一起使用:

main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

import './provider_model.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChangeNotifierProvider(
          create: (BuildContext context) => ProviderModel(),
          child: Scaffold(
            body: MyHomePage(),
          )),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _controller = TextEditingController();

  final _channel = WebSocketChannel.connect(
    Uri.parse('wss://echo.websocket.events'),
  );

  @override
  Widget build(BuildContext context) {
    return Consumer<ProviderModel>(
      builder: (context, provider, _) {
        return Column(children: [
          TextField(
            controller: _controller,
            decoration: InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter a search term',
                suffixIcon: IconButton(
                    icon: Icon(
                      Icons.send,
                    ),
                    onPressed: _sendMessage)),
          ),
          ...provider.myList.map((e) => Text(e)).toList(),
          StreamBuilder(
            stream: _channel.stream,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                // ERROR HERE!
                provider.addItem('I was added');
                return Text("Item added");
              } else if (snapshot.hasError) {
                return Text(snapshot.error as String);
              } else {
                return CircularProgressIndicator();
              }
            },
          )
        ]);
      },
    );
  }

  void _sendMessage() {
    if (_controller.text.isNotEmpty) {
      _channel.sink.add(_controller.text);
      print('done');
    }
  }
}

Which the following output (Chrome):以下输出(Chrome): 在此处输入图像描述 Now, when I click on the send button, it calls _sendMessage() (code above).现在,当我单击发送按钮时,它会调用_sendMessage() (上面的代码)。 And then since the StreamBuilder() hasData it runs this line (code above):然后由于StreamBuilder() hasData它运行这一行(上面的代码):

provider.addItem('I was added');

However, this is where my error appears, I am getting the following error:但是,这是我的错误出现的地方,我收到以下错误:

The following assertion was thrown while dispatching notifications for ProviderModel:
setState() or markNeedsBuild() called during build.

You can take help from addPostFrameCallback , but the cost is it will keep rebuilding on every frame, to control this behavior you can use a bool on state class.您可以从addPostFrameCallback帮助,但代价是它将在每一帧上继续重建,为了控制这种行为,您可以在状态类上使用 bool。

  bool isDone = false;

  void addItemH() {
    if (!isDone) {
      WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
        Provider.of<ProviderModel>(context, listen: false)
            .addItem('I was added');
        isDone = true;
      });
    }
  }

And builder和建设者

 builder: (context, snapshot) {
                if (snapshot.hasData) {
                  addItemH();
                  return Text("Item added");

And to control the next insertaion.并控制下一次插入。

  void _sendMessage() {
    if (_controller.text.isNotEmpty) {
      isDone = false;
      _channel.sink.add(_controller.text);
      print('done');
    }
  }
}

If you just want to add data only single time, it is better to do inside inside initState.如果你只想单次添加数据,最好在 initState 里面做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 颤振)蓝牙提供程序错误=&gt;setState()或markNeedsBuild()在构建期间调用 - flutter) Bluetooth provider error =>setState() or markNeedsBuild() called during build 在构建期间调用 Flutter 提供程序抛出错误 setState() 或 markNeedsBuild() - Flutter provider throwing error setState() or markNeedsBuild() called during build Flutter:setState() 或 markNeedsBuild() 在使用 Provider 构建期间调用 - Flutter: setState() or markNeedsBuild() called during build with Provider setState() 或 markNeedsBuild() 在使用 Provider 构建期间调用 - setState() or markNeedsBuild() called during build with Provider Flutter:提供程序 class 中出现“构建期间调用的 setState() 或 markNeedsBuild()”错误 - Flutter: "setState() or markNeedsBuild() called during build" error in provider class Flutter - 提供者 - 在构建期间调用 setstate 或 markneedsbuild() - Flutter - Provider - setstate or markneedsbuild() called during build 提供者:在构建期间调用的 setState() 或 markNeedsBuild() - Provider: setState() or markNeedsBuild() called during build Flutter 在构建过程中调用了 Provider setState() 或 markNeedsBuild() - Flutter Provider setState() or markNeedsBuild() called during build 在构建期间调用 setState() 或 markNeedsBuild(),在 Flutter 中使用 FutureBuilder 中的 Provider 和 StreamBuilder - setState() or markNeedsBuild() called during build, using Provider inside FutureBuilder and StreamBuilder in Flutter StreamBuilder / ChangeNotifierProvider- setState() 或 markNeedsBuild() 在构建期间调用 - StreamBuilder / ChangeNotifierProvider- setState() or markNeedsBuild() called during build
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM