本文介绍了当我尝试在构建器中显示SnackBar时出现错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的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)));
}
}

我想在FutureBuilder中显示一个SnackBar,但是当我运行时,发生了一些错误:

I'd like to show a SnackBar in FutureBuilder, but when I run, something wrong occurs:

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

我的目的是在获取数据之前显示加载微调器,一旦获取数据,则显示SnackBar.那我该怎么做才能解决这个问题呢? Login.main是从数据库中获取数据的功能.

My purpose is that it shows a loading spinner before it gets the data, and once it got the data, it shows a SnackBar. So what should I do to fix the problem? Login.main is a function that GET data from the database.

推荐答案

FutureBuilderStreamBuilder应该仅用于构建窗口小部件,而不用于执行导航之类的逻辑.改为使用initState喜欢

FutureBuilder or StreamBuilder should only used to build widgets, not to execute logic like navigation. Use instead initState like

@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())
      ),
    ),
  );
}

这篇关于当我尝试在构建器中显示SnackBar时出现错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 11:45
查看更多