Flutter 尝试在生成器中显示SnackBar时出错
这是我的Flutter 尝试在生成器中显示SnackBar时出错,flutter,flutter-animation,Flutter,Flutter Animation,这是我的main.dart: class MyApp extends StatelessWidget { var login = new Login("xxxxxxx", "xxxxxxxxx"); final scaffoldKey = new GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data
main.dart
:
class MyApp extends StatelessWidget {
var login = new Login("xxxxxxx", "xxxxxxxxx");
final scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
child: FutureBuilder(
future: login.main(),
builder: (context, snapshot) {
if (snapshot.hasData) {
_showSnackBar(snapshot.data);
return new Container();
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner
return CircularProgressIndicator();
},
),
),
),
);
}
_showSnackBar(var text) {
scaffoldKey.currentState
.showSnackBar(new SnackBar(content: new Text(text)));
}
}
类MyApp扩展了无状态小部件{
var登录=新登录(“XXXXXXXX”、“XXXXXXXX”);
最终脚手架键=新的GlobalKey();
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“获取数据示例”,
主题:主题数据(
主样本:颜色。蓝色,
),
家:脚手架(
钥匙:脚手架钥匙,
appBar:appBar(
标题:文本(“获取数据示例”),
),
正文:中(
孩子:未来建设者(
future:login.main(),
生成器:(上下文,快照){
if(snapshot.hasData){
_showSnackBar(snapshot.data);
返回新容器();
}else if(snapshot.hasrerror){
返回文本(“${snapshot.error}”);
}
//默认情况下,显示加载微调器
返回循环ProgressIndicator();
},
),
),
),
);
}
_showSnackBar(变量文本){
scaffoldKey.currentState
.showSnackBar(新SnackBar(内容:新文本(Text)));
}
}
我想在FutureBuilder中显示SnackBar,但当我运行时,出现了一些错误:
I/flutter ( 8918): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
I/flutter ( 8918): The following assertion was thrown building
FutureBuilder<dynamic>(dirty, state:
I/flutter ( 8918): _FutureBuilderState<dynamic>#9d4af):
I/flutter ( 8918): setState() or markNeedsBuild() called during build.
I/flutter ( 8918): This Scaffold widget cannot be marked as needing to
build because the framework is already in the
I/flutter ( 8918): process of building widgets. A widget can be marked
as needing to be built during the build phase
I/flutter ( 8918): only if one of its ancestors is currently building.
This exception is allowed because the framework
I/flutter ( 8918): builds parent widgets before children, which means
a dirty descendant will always be built.
I/flutter ( 8918): Otherwise, the framework might not visit this
widget during this build phase.
I/flutter ( 8918): The widget on which setState() or markNeedsBuild()
was called was:
I/flutter ( 8918): Scaffold-[LabeledGlobalKey<ScaffoldState>#e4a3f]
(state: ScaffoldState#cf908(tickers: tracking 2
I/flutter ( 8918): tickers))
I/flutter ( 8918): The widget which was currently being built when the
offending call was made was:
I/flutter ( 8918): FutureBuilder<dynamic>(dirty, state: _
FutureBuilderState<dynamic>#9d4af)
I/flutter ( 8918):
I/flutter ( 8918): When the exception was thrown, this was the stack:
I/flutter ( 8918): #0 Element.markNeedsBuild.<anonymous closure>
(package:flutter/src/widgets/framework.dart:3472:11)
I/flutter ( 8918): #1 Element.markNeedsBuild
(package:flutter/src/widgets/framework.dart:3498:6)
I/flutter ( 8918): #2 State.setState
(package:flutter/src/widgets/framework.dart:1141:14)
I/flutter ( 8918): #3 ScaffoldState.showSnackBar
(package:flutter/src/material/scaffold.dart:1110:5)
I/flutter ( 8918): #4 MyApp._showSnackBar
I/flutter ( 8918): #5 MyApp.build.<anonymous closure>
I/flutter ( 8918): #6 _FutureBuilderState.build
(package:flutter/src/widgets/async.dart)
I/flutter ( 8918): #7 StatefulElement.build
(package:flutter/src/widgets/framework.dart:3766:27)
I/flutter ( 8918): #8 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:3678:15)
I/flutter ( 8918): #9 Element.rebuild
(package:flutter/src/widgets/framework.dart:3531:5)
I/flutter ( 8918): #10 BuildOwner.buildScope
(package:flutter/src/widgets/framework.dart:2273:33)
I/flutter ( 8918): #11
I/颤振(8918):══╡ WIDGETS库捕获到异常
╞═══════════════════════════════════════════════════════════
I/flatter(8918):以下断言被抛出
FutureBuilder(脏,状态:
I/颤振(8918):_FutureBuilderState#9d4af):
I/flatter(8918):在生成过程中调用setState()或markNeedsBuild()。
I/颤振(8918):此脚手架小部件不能标记为需要
构建,因为框架已经在
I/flatter(8918):构建小部件的过程。可以标记小部件
因为需要在构建阶段构建
I/Flatter(8918):仅当其祖先之一正在建造时。
此异常是允许的,因为框架
I/flatter(8918):在子部件之前构建父部件,这意味着
一个肮脏的后代将永远被建造。
I/flatter(8918):否则,框架可能不会访问此
此构建阶段中的小部件。
I/flatter(8918):setState()或markNeedsBuild()所在的小部件
被称为:
I/颤振(8918):脚手架-[贴有标签的Lobalkey#e4a3f]
(州:脚手架州#cf908(股票行情:跟踪2)
I/颤振(8918):股票)
I/flatter(8918):当
发出的违规电话是:
我/弗利特(8918):FutureBuilder(肮脏,州:)
FutureBuilderState#9d4af)
I/颤振(8918):
I/flatter(8918):当抛出异常时,这是堆栈:
I/颤振(8918):#0元素。标记需要构建。
(包:flatter/src/widgets/framework.dart:3472:11)
I/颤振(8918):#1个元素。标记需要构建
(包:flatter/src/widgets/framework.dart:3498:6)
I/颤振(8918):#2 State.setState
(包:flatter/src/widgets/framework.dart:1141:14)
I/颤振(8918):#3 ScaffoldState.showSnackBar
(包装:颤振/src/材料/脚手架。省道:1110:5)
I/flatter(8918):#4我的应用程序。_showSnackBar
I/flatter(8918):#5 MyApp.build。
I/flatter(8918):#6#FutureBuilderState.build
(包:flatter/src/widgets/async.dart)
I/flatter(8918):#7 StatefulElement.build
(包:flatter/src/widgets/framework.dart:3766:27)
I/颤振(8918):#8组件元素。性能构建
(包:flatter/src/widgets/framework.dart:3678:15)
I/颤振(8918):#9个元素。重建
(包:flatter/src/widgets/framework.dart:3531:5)
I/颤振(8918):#10 BuildOwner.buildScope
(包:flatter/src/widgets/framework.dart:2273:33)
I/颤振(8918):#11
我的目的是在它获取数据之前显示一个加载微调器,一旦它获取了数据,它就会显示一个SnackBar。那么我应该怎么做来解决这个问题呢
Login.main
是一个从数据库获取数据的函数 您可以这样尝试:修改showSnackBar并传递上下文吗
_showSnackBar(var text, BuildContext context) {
ScaffoldKey.of(context)
.showSnackBar(new SnackBar(content: new Text(text)));
}
FutureBuilder
或StreamBuilder
应仅用于构建小部件,而不是执行导航之类的逻辑。使用类似的initState
@override
void initState() {
super.initState();
_checkLogin();
}
Future<void> _checkLogin() async {
try {
var data = await login.main();
setState(() {
_waitForLogin = false;
});
_showSnackBar(data);
} catch(e) {
setState(() {
_waitForLogin = false;
_loginErrorMessage = '$e';
});
}
}
bool _isWaitForLogin = true;
String _loginErrorMessage;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text('Fetch Data Example'),
),
body: Center(
child: _isWaitForLogin ? CircularProgressIndicator() :
(_loginErrorMessage != null ? Text(_loginErrorMessage : Container())
),
),
);
}
@覆盖
void initState(){
super.initState();
_checkLogin();
}
Future\u checkLogin()异步{
试一试{
var data=await login.main();
设置状态(){
_waitForLogin=false;
});
_showSnackBar(数据);
}捕获(e){
设置状态(){
_waitForLogin=false;
_loginErrorMessage='$e';
});
}
}
bool_isWaitForLogin=true;
字符串\u loginErrorMessage;
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“获取数据示例”,
主题:主题数据(
主样本:颜色。蓝色,
),
家:脚手架(
钥匙:脚手架钥匙,
appBar:appBar(
标题:文本(“获取数据示例”),
),
正文:中(
子项:_isWaitForLogin?CircularProgressIndicator():
(_loginErrorMessage!=null?文本(_loginErrorMessage:Container())
),
),
);
}
建议将中断逻辑包装在WidgetsBinding.instance.addPostFrameCallback(({}
)中。例如:
builder: (context, AsyncSnapshot<Object> snapshot) {
if (snapshot.hasError) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Scaffold.of(context)
..hideCurrentSnackBar()
..showSnackBar(
// SnackBar
);
});
return Container();
}
// Rest ...
}
builder:(上下文,异步快照){
if(snapshot.hasError){
WidgetsBinding.instance.addPostFrameCallback((){
脚手架(上下文)
…hideCurrentSnackBar()
...............展示小吃吧(
//小吃条
);
});
返回容器();
}
//休息。。。
}
在(\u loginErrorMessage!=null?Text(\u loginErrorMessage?Container())
处有一个错误。它显示“条件必须具有静态类型的'bool'”。我有一个?
,其中:
应该是。请重试。