【问题标题】:Calling a function on an event from another class Flutter从另一个类 Flutter 调用事件的函数
【发布时间】:2019-03-13 13:17:25
【问题描述】:

我一直遇到 Flutter 的这个问题,我不知道如何处理它。我试图通过一些教程,然后我想这样做。

我想要做的是从 onPresssed 事件 ._increment 上的 FloatingActionButton 调用,以便我可以增加 _counter。但后来我得到了那个错误。 我错过了什么?

void main() {
  runApp(MaterialApp(
    title: 'Flutter Tutorial',
    home: TutorialHome(),
  ));
}

class TutorialHome extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    // Scaffold is a layout for the major Material Components.
    SystemChrome.setEnabledSystemUIOverlays([]); //Hide Status Bar
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.menu),
          tooltip: 'Navigation menu',
          onPressed: null,
        ),
        title: Text('Example title'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.search),
            tooltip: 'Search',
            onPressed: null,
          ),
        ],
      ),
      // body is the majority of the screen.
      body: Center(
        child: Container(
          height: 100,
          width: 100,
          child: Column(
            children: <Widget>[
              Counter(),
            ]
          )
        )
      ),
      floatingActionButton: FloatingActionButton(
        tooltip: 'Add', // used by assistive technologies
        child: Icon(Icons.add),
        onPressed: _CounterState()._increment,
      ),
    );
  }
}


//class CounterIncrementor extends StatelessWidget {
//  CounterIncrementor({this.onPressed});
//
//  final VoidCallback onPressed;
//
//  @override
//  Widget build(BuildContext context) {
//    return RaisedButton(
//      onPressed: onPressed,
//      child: Text('Increment'),
//    );
//  }
//}

class Counter extends StatefulWidget {
  // This class is the configuration for the state. It holds the
  // values (in this case nothing) provided by the parent and used by the build
  // method of the State. Fields in a Widget subclass are always marked "final".

  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _counter = 0;

  void _increment() {
    setState(() {
      // This call to setState tells the Flutter framework that
      // something has changed in this State, which causes it to rerun
      // the build method below so that the display can reflect the
      // updated values. If we changed _counter without calling
      // setState(), then the build method would not be called again,
      // and so nothing would appear to happen.
      print("Increasing counter value\n");
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance
    // as done by the _increment method above.
    // The Flutter framework has been optimized to make rerunning
    // build methods fast so that you can just rebuild anything that
    // needs updating rather than having to individually change
    // instances of widgets.
    return Column(
      children: <Widget>[
        RaisedButton(
          onPressed: _increment,
          child: Text('Increment'),
        ),
        Text('Count: $_counter'),
      ],
    );
  }
}

这是错误:

 ************************ ERROR *************************
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (20840): The following assertion was thrown while handling a gesture:
I/flutter (20840): setState() called in constructor: _CounterState#452ba(lifecycle state: created, no widget, not
I/flutter (20840): mounted)
I/flutter (20840): This happens when you call setState() on a State object for a widget that hasn't been inserted into
I/flutter (20840): the widget tree yet. It is not necessary to call setState() in the constructor since the state is
I/flutter (20840): already assumed to be dirty when it is initially created.

【问题讨论】:

    标签: dart flutter flutter-layout


    【解决方案1】:

    所以检查你的代码我发现你有 2 个按钮:

    FloatingActionButton
    

    RaisedButton
    

    两者的区别在于

    • RaisedButton 按下时从 _CounterState 的实例对象调用方法 _increment 并且该对象已安装(此 _CounterState 对象创建 RaisedButton)李>
    • FloatingActionButton 在按下时调用方法来创建一个新的 _CounterState() 对象,然后在该对象上增加计数器。新状态与显示的任何内容无关。它只是一个新对象(未插入到小部件树中)。

    你在 TutorialHome 中实例化了一个计数器

    //...
    child: Column(
                      children: <Widget>[
                        Counter(), 
                      ]
                  )
    
    //...
    

    此计数器有责任为自己创建状态(_CounterState 对象)。

    应要求更新:

    这不是一个干净的代码,它只是用于演示。

    下面有一个示例,说明如何使用流控制器(您的计数器和从其他地方按下的按钮)在两个对象之间设置信息交换......以一种草率的方式。

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MaterialApp(
        title: 'Flutter Tutorial',
        home: TutorialHome(),
      ));
    }
    
    class TutorialHome extends StatelessWidget {
    
      StreamController<void> buttonPressStream = StreamController<bool>.broadcast();
    
      @override
      Widget build(BuildContext context) {
        // Scaffold is a layout for the major Material Components.
    
        return Scaffold(
          appBar: AppBar(
            leading: IconButton(
              icon: Icon(Icons.menu),
              tooltip: 'Navigation menu',
              onPressed: null,
            ),
            title: Text('Example title'),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.search),
                tooltip: 'Search',
                onPressed: null,
              ),
            ],
          ),
          // body is the majority of the screen.
          body: Center(
              child: Container(
                  height: 100,
                  width: 100,
                  child: Column(
                      children: <Widget>[
                        Counter(buttonPressStream),
                      ]
                  )
              )
          ),
          floatingActionButton: FloatingActionButton(
            tooltip: 'Add', // used by assistive technologies
            child: Icon(Icons.add),
            onPressed: () => buttonPressStream.add(null),
          ),
        );
      }
    }
    
    
    //class CounterIncrementor extends StatelessWidget {
    //  CounterIncrementor({this.onPressed});
    //
    //  final VoidCallback onPressed;
    //
    //  @override
    //  Widget build(BuildContext context) {
    //    return RaisedButton(
    //      onPressed: onPressed,
    //      child: Text('Increment'),
    //    );
    //  }
    //}
    
    class Counter extends StatefulWidget {
      // This class is the configuration for the state. It holds the
      // values (in this case nothing) provided by the parent and used by the build
      // method of the State. Fields in a Widget subclass are always marked "final".
    
      final StreamController<void> buttonPressStream;
    
      const Counter(this.buttonPressStream);
    
      @override
      _CounterState createState() => _CounterState(buttonPressStream);
    }
    
    class _CounterState extends State<Counter> {
      int _counter = 0;
    
      StreamController<void> buttonPressStream;
      _CounterState(this.buttonPressStream);
    
      void _increment() {
        setState(() {
          // This call to setState tells the Flutter framework that
          // something has changed in this State, which causes it to rerun
          // the build method below so that the display can reflect the
          // updated values. If we changed _counter without calling
          // setState(), then the build method would not be called again,
          // and so nothing would appear to happen.
          print("Increasing counter value\n");
          _counter++;
        });
      }
    
      @override
      void initState() {
        super.initState();
        buttonPressStream.stream.listen( (_) {
          setState(() {});
        });
      }
    
    
    
      @override
      Widget build(BuildContext context) {
        // This method is rerun every time setState is called, for instance
        // as done by the _increment method above.
        // The Flutter framework has been optimized to make rerunning
        // build methods fast, so that you can just rebuild anything that
        // needs updating rather than having to individually change
        // instances of widgets.
        return Column(
          children: <Widget>[
            RaisedButton(
              onPressed: _increment,
              child: Text('Increment'),
            ),
            Text('Count: $_counter'),
          ],
        );
      }
    }
    

    【讨论】:

    • 是的,我明白这一点。在我的情况下,如果我想更新计数器,我可以从FloatingActionButton 进行吗?
    • 没问题本尼
    猜你喜欢
    • 2020-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多