【问题标题】:Flutter web, update navbar after authorizationFlutter web,授权后更新navbar
【发布时间】:2020-09-06 12:29:01
【问题描述】:

我正在尝试使用 Flutter 创建一个 Web 应用程序,但我有一个问题。通过授权后,我需要更改导航栏中的“登录”按钮,据我了解,我需要更改按钮文本并在导航栏中调用 setState,但在我的实现中引发了异常。

AuthPage.dart

import 'package:flutter/material.dart';
import 'package:um/pages/home/app_color.dart';
import 'package:um/scripts/api_client.dart';
import 'package:um/scripts/locator.dart';

import 'NavBarDesktop.dart';

class AuthorizationPageDesktop extends StatefulWidget {
  AuthorizationPageDesktop({Key key}) : super(key: key);

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

class _AuthorizationPageDesktopState extends State<AuthorizationPageDesktop> {
  TextEditingController _emailController = TextEditingController();
  TextEditingController _passwordController = TextEditingController();
  bool rememberMe = false;
  ApiClient apiClient = ApiClient.getInstance();
  ScrollController _scrollController = ScrollController();
  PageController _pageController = PageController();

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
        child: Container(
            child: Padding(
      padding: EdgeInsets.only(top: 150, left: 0, right: 0),
      child: Column(
        children: <Widget>[
          Text(
            'Авторизация',
            style: TextStyle(
                fontWeight: FontWeight.w600,
                fontSize: 28,
                color: textPrimaryColor),
          ),
          SizedBox(
            height: 40,
          ),
          _input(Icon(Icons.mail), 'Email', _emailController, false, 15),
          SizedBox(
            height: 15,
          ),
          _input(Icon(Icons.lock), 'Password', _passwordController, true, 15),
          SizedBox(
            height: 5,
          ),
          Container(
              padding: EdgeInsets.only(left: 20, right: 20),
              width: 460,
              child: Theme(
                  data: ThemeData(
                      splashColor: Colors.transparent,
                      highlightColor: Colors.transparent,
                      hoverColor: Colors.transparent),
                  child: CheckboxListTile(
                    title: Text(
                      'Запомнить меня',
                      style: TextStyle(color: textPrimaryColor),
                    ),
                    value: rememberMe,
                    onChanged: (bool value) {
                      setState(() {
                        rememberMe = value;
                      });
                    },
                  ))),
          SizedBox(
            height: 5,
          ),
          _button('Войти', auth, 15),
          SizedBox(
            height: 15,
          ),
          Container(
            width: 460,
            child: Align(
                alignment: Alignment.bottomCenter,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      'Пройдите ',
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    ),
                    Text(
                      'регистрацию, ',
                      style: TextStyle(color: linkColor, fontSize: 12),
                    ),
                    Text(
                      'если вы этого еще не сделали',
                      style: TextStyle(color: Colors.white, fontSize: 12),
                    ),
                  ],
                )),
          ),
          SizedBox(height: 50),
        ],
      ),
    )));
  }

  Widget _input(Icon icon, String hint, TextEditingController controller,
      bool obscure, double borderRadius) {
    return Container(
      width: 460,
      height: 50,
      padding: EdgeInsets.only(left: 20, right: 20),
      child: TextField(
        controller: controller,
        obscureText: obscure,
        style: TextStyle(fontSize: 16, color: Colors.white),
        decoration: InputDecoration(
            border: OutlineInputBorder(),
            isDense: true, // Added this
            contentPadding: EdgeInsets.all(8), //

            hintStyle: TextStyle(
                fontWeight: FontWeight.bold, fontSize: 16, color: Colors.white),
            hintText: hint,
            focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(borderRadius),
                borderSide: BorderSide(color: Colors.white, width: 2)),
            enabledBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(borderRadius),
                borderSide: BorderSide(color: Colors.white54, width: 1)),
            prefixIcon: Padding(
              padding: EdgeInsets.only(left: 10, right: 10),
              child: IconTheme(
                data: IconThemeData(color: Colors.white),
                child: icon,
              ),
            )),
      ),
    );
  }

  Widget _button(String label, void func(), double borderRadius) {
    return Container(
        width: 460,
        padding: EdgeInsets.only(left: 20, right: 20),
        child: RaisedButton(
          onPressed: () {
            apiClient
                .authorization(_emailController.text, _passwordController.text)
                .then((value) {
              func();
            });
          },
          highlightColor: Theme.of(context).primaryColor,
          color: buttonPrimaryColor,
          child: Text('Войти',
              style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: textPrimaryColor,
                  fontSize: 16)),
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(borderRadius)),
        ));
  }

  void auth() {
    var state = navBar<NavBarDesktop>().navBarState;
    state.update();
  }
}

NavBar.dart

import 'package:flutter/material.dart';
import 'package:um/Widgets/Desktop/AuthPageDesktop.dart';
import 'package:um/Widgets/Desktop/HomePageDesktop.dart';
import 'package:um/Widgets/NavBarItem.dart';
import 'package:um/layout_template/layout_template.dart';
import 'package:um/pages/home/app_color.dart';
import 'package:um/scripts/api_client.dart';
import 'package:um/scripts/locator.dart';

class NavBarDesktop extends StatefulWidget {
  NavBarDesktop({Key key}) : super(key: key);

  GlobalKey<_NavBarDesktopState> navBarDesktop =
      GlobalKey<_NavBarDesktopState>();

  _NavBarDesktopState navBarState = new _NavBarDesktopState();

  static _NavBarDesktopState of(BuildContext context) {
    // print('_NavBarDesktopState -> ${context}');
    assert(context != null);
    final _NavBarDesktopState result =
        // ignore: deprecated_member_use
        context.ancestorStateOfType(const TypeMatcher<_NavBarDesktopState>());
    // print('_NavBarDesktopState resutl -> ${result}');
    return result;
  }

  @override
  _NavBarDesktopState createState() => new _NavBarDesktopState();
}

class _NavBarDesktopState extends State<NavBarDesktop> {
  String authButtonTitle = "Войти";

  @override
  void initState() {
    print('call init state navbar ${ApiClient.username}');
    if (ApiClient.username != null && ApiClient.username.length > 0)
      authButtonTitle = ApiClient.username;
    super.initState();
  }

  void update() {
    setState(() {
      authButtonTitle = ApiClient.username;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      color: primaryColor,
      height: 50,
      padding: EdgeInsets.only(left: 50, right: 50),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          GestureDetector(
              onTap: () {
                LayoutTemplate.of(context).change_page(HomePageDesktop());
              },
              child: Text(
                'UM',
                textAlign: TextAlign.center,
                style: TextStyle(
                    color: textPrimaryColor,
                    fontWeight: FontWeight.w600,
                    fontSize: 40),
              )),
          NavBarItem(
              authButtonTitle,
              () => LayoutTemplate.of(context)
                  .change_page(AuthorizationPageDesktop())),
        ],
      ),
    );
  }

  void auth_page_up(BuildContext context) {
    LayoutTemplate.of(context).change_page(AuthorizationPageDesktop());
  }
}

例外

Error: setState() called in constructor: _NavBarDesktopState#5e1ee(lifecycle state: created, no widget, not mounted)
This happens when you call setState() on a State object for a widget that hasn't been inserted into the widget tree yet. It is not necessary to   
call setState() in the constructor, since the state is already assumed to be dirty when it is initially created.
    at Object.throw_ [as throw] (http://localhost:50572/dart_sdk.js:4334:11)
    at http://localhost:50572/packages/flutter/src/widgets/widget_span.dart.lib.js:13615:23
    at NavBarDesktop._NavBarDesktopState.new.setState (http://localhost:50572/packages/flutter/src/widgets/widget_span.dart.lib.js:13618:26)      
    at NavBarDesktop._NavBarDesktopState.new.update (http://localhost:50572/packages/um/scripts/router.dart.lib.js:1717:12)
    at AuthPageDesktop._AuthorizationPageDesktopState.new.auth (http://localhost:50572/packages/um/scripts/router.dart.lib.js:1932:13)
    at http://localhost:50572/packages/um/scripts/router.dart.lib.js:1926:15
    at _RootZone.runUnary (http://localhost:50572/dart_sdk.js:37457:58)
    at _FutureListener.then.handleValue (http://localhost:50572/dart_sdk.js:32441:29)
    at handleValueCallback (http://localhost:50572/dart_sdk.js:32988:49)
    at Function._propagateToListeners (http://localhost:50572/dart_sdk.js:33026:17)
    at _Future.new.[_completeWithValue] (http://localhost:50572/dart_sdk.js:32869:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:50572/dart_sdk.js:32891:35)
    at Object._microtaskLoop (http://localhost:50572/dart_sdk.js:37718:13)
    at _startMicrotaskLoop (http://localhost:50572/dart_sdk.js:37724:13)
    at http://localhost:50572/dart_sdk.js:33243:9

【问题讨论】:

    标签: flutter dart flutter-web


    【解决方案1】:

    您的 _NavBarDesktopState 全局键需要在您的 _NavBarDesktopState 类中初始化,而不是在 NavBarDesktop 类中。它试图在状态创建之前设置全局键。

    【讨论】:

      【解决方案2】:
      class NavBarDesktop extends StatefulWidget {
        NavBarDesktop({Key key}) : super(key: key);
        _NavBarDesktopState navBarState;
      
        static _NavBarDesktopState of(BuildContext context) {
          assert(context != null);
          final _NavBarDesktopState result =
              // ignore: deprecated_member_use
              context.ancestorStateOfType(const TypeMatcher<_NavBarDesktopState>());
          return result;
        }
      
        @override
        _NavBarDesktopState createState() {
          navBar.registerLazySingleton(() => this);
          navBarState = _NavBarDesktopState();
          return navBarState;
        }
      }
      
      

      【讨论】:

        猜你喜欢
        • 2020-06-26
        • 2020-11-12
        • 2018-06-13
        • 1970-01-01
        • 1970-01-01
        • 2022-11-21
        • 1970-01-01
        • 2014-01-04
        • 2019-11-07
        相关资源
        最近更新 更多