在另一个类Flutter上的事件上调用函数 [英] Calling a function on an event from another class Flutter

查看:516
本文介绍了在另一个类Flutter上的事件上调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Flutter遇到了这个问题,我不知道该如何处理。我试图浏览一些教程,然后我想这样做。

I've been having this problem with Flutter and I don't know how to handle it. I was trying to go through some of the tutorials and then I wanted to do this.

我要做的是从<$ c $上的FloatingActionButton调用c> onPresssed 事件 ._ increment ,这样我就可以增加 _counter 。但是后来我得到了那个错误。
我缺少了什么?

What I want to do is to call from the FloatingActionButton on the onPresssed event ._increment, so that I can increment the _counter. But then I get that error. What am I missing?

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.


推荐答案

所以检查代码,我发现您有2个按钮:

So checking your code I saw that you have 2 buttons:

FloatingActionButton

RaisedButton

两者之间的区别是


  • RaisedButton _CounterState 的实例对象中的方法 _increment ,并且该对象已经安装(此_CounterState对象创建RaisedButton)

  • FloatingActionButton 会调用该方法来创建一个新的 _CounterState()对象,然后在该对象增量计数器上。新状态与显示的内容无关。

  • RaisedButton on pressed calls the method _increment from the instance object of _CounterState and this object is already mounted (this _CounterState object creates the RaisedButton)
  • FloatingActionButton on pressed calls the method to create a NEW _CounterState() object and then on that object increment counter. The new state has nothing to do with anything that is displayed. It is a just new object (not inserted in the widget tree).

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

You instantiate a Counter in TutorialHome

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

//...



<该计数器负责为其自身创建状态(_CounterState对象)。

This Counter has the responsibility to create states for itself (_CounterState objects).

根据要求更新:

这不是一个干净的代码,它是

This is not a clean code and it is only for demo.

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

Below you have an example on how to setup info exchange between two objects using a stream controller (your counter and the button pressed from somewhere else)... in a sloppy way.

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'),
      ],
    );
  }
}

这篇关于在另一个类Flutter上的事件上调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆