问题描述
我一直遇到 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.
我想做的是从 onPresssed
事件 ._increment
上的 FloatingActionButton 调用,以便我可以递增 _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
");
_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
");
_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 调用事件的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!