简体   繁体   English

Flutter:当小部件树被锁定时调用 setState() 或 markNeedsBuild() ... 在方向更改期间

[英]Flutter: setState() or markNeedsBuild() called when widget tree was locked... during orientation change

I want to create a App whose UI can be updated based on device orientation.我想创建一个可以根据设备方向更新 UI 的应用程序。 In Portait layout, i use a drawer to show some elements ( Fig. ).在 Portait 布局中,我使用抽屉来显示一些元素()。 In Landscape layout, there is no drawer but the elements are showed in a column at left of screen ( Fig. ).在横向布局中,没有抽屉,但元素显示在屏幕左侧的一列中()。 The program works, when the drawer is closed.该程序在抽屉关闭时运行。

But when i switch orientation from portait to landscape with drawer opened , i got error of "setState() or markNeedsBuild() called when widget tree was locked" The stack provides this info:但是当我在打开抽屉的情况下将方向从纵向切换到横向时,我收到错误消息“setState() or markNeedsBuild() called when widget tree was locked”堆栈提供了以下信息:

Built build\app\outputs\apk\debug\app-debug.apk.
I/FlutterActivityDelegate(28527): onResume setting current activity to this
I/flutter (28527): PORTRAIT LAYOUT!!!!!!!!!!!!!!!!!!!!!!
I/hwaps   (28527): JNI_OnLoad
I/flutter (28527): LANDSCAPE LAYOUT!!!!!!!!!!!!!!!!!!!!!!
I/flutter (28527): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (28527): The following assertion was thrown while finalizing the widget tree:
I/flutter (28527): setState() or markNeedsBuild() called when widget tree was locked.
I/flutter (28527): This _ModalScope<dynamic> widget cannot be marked as needing to build because the framework is
I/flutter (28527): locked.
I/flutter (28527): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (28527):   _ModalScope<dynamic>-[LabeledGlobalKey<_ModalScopeState<dynamic>>#e1f0f](state:
I/flutter (28527):   _ModalScopeState<dynamic>#830e3)
I/flutter (28527):
I/flutter (28527): When the exception was thrown, this was the stack:
I/flutter (28527): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3453:9)
I/flutter (28527): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3462:6)
I/flutter (28527): #2      State.setState (package:flutter/src/widgets/framework.dart:1141:14)
I/flutter (28527): #3      _ModalScopeState._routeSetState (package:flutter/src/widgets/routes.dart:464:5)
I/flutter (28527): #4      ModalRoute.setState (package:flutter/src/widgets/routes.dart:562:30)
I/flutter (28527): #5      ModalRoute.changedInternalState (package:flutter/src/widgets/routes.dart:1018:5)
I/flutter (28527): #6      _ModalRoute&TransitionRoute&LocalHistoryRoute.removeLocalHistoryEntry (package:flutter/src/widgets/routes.dart:348:7)
I/flutter (28527): #7      LocalHistoryEntry.remove (package:flutter/src/widgets/routes.dart:296:12)
I/flutter (28527): #8      DrawerControllerState.dispose (package:flutter/src/material/drawer.dart:201:20)
I/flutter (28527): #9      StatefulElement.unmount (package:flutter/src/widgets/framework.dart:3821:12)
I/flutter (28527): #10     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1697:13)
I/flutter (28527): #11     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1695:7)
I/flutter (28527): #12     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3676:14)
I/flutter (28527): #13     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1693:13)
I/flutter (28527): #14     _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1695:7)
I/flutter (28527): #15     ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3676:14)
I/flutter (28527): #16     _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1693:13)
I/flutter (28527): #17     ListIterable.forEach (dart:_internal/iterable.dart:39:13)
I/flutter (28527): #18     _InactiveElements._unmountAll (package:flutter/src/widgets/framework.dart:1706:25)
I/flutter (28527): #19     BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2328:27)
I/flutter (28527): #20     BuildOwner.lockState (package:flutter/src/widgets/framework.dart:2160:15)
I/flutter (28527): #21     BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2327:7)
I/flutter (28527): #22     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:628:18)
I/flutter (28527): #23     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
I/flutter (28527): #24     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter (28527): #25     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter (28527): #26     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter (28527): #27     _invoke (dart:ui/hooks.dart:120:13)
I/flutter (28527): #28     _drawFrame (dart:ui/hooks.dart:109:3)
I/flutter (28527): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.
I/flutter (28527): Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3424 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true.

And i got a go back button at leading of Appbar( Fig. ).我在 Appbar 的前面有一个 go 后退按钮()。

Here is my code:这是我的代码:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'demo',
      theme: new ThemeData(primarySwatch: Colors.blue),
      home: new Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  static const int SCREEN_WIDTH_MIN = 600;

  @override
  Widget build(BuildContext context) {
    Widget _homelayout;
    var screenWidth = MediaQuery.of(context).size.width;
    var screenOrientation = MediaQuery.of(context).orientation;
    if ((screenWidth > SCREEN_WIDTH_MIN) &&
        (screenOrientation == Orientation.landscape)) {
      print('LANDSCAPE LAYOUT!!!!!!!!!!!!!!!!!!!!!!');
      //_homelayout = _buildLandscapeLayout(context);
      _homelayout = _buildLandscapeLayout();
    } else {
      print('PORTRAIT LAYOUT!!!!!!!!!!!!!!!!!!!!!!');
      _homelayout = _buildPortraitLayout();
    }
    return _homelayout;
  }

  Widget _buildPortraitLayout() {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('demo'),
      ),
      drawer: new DeviceListDrawer(),
      body: new Center(
        child: new Text('body'),
      ),
    );
  }
}

Widget _buildLandscapeLayout() {
  return new Scaffold(
    appBar: new AppBar(
      title: new Text('demo'),
    ),
    body: new Center(
      child: new Row(
        children: <Widget>[
          new DeviceListDrawer(),
          new Text('body')
        ],
      ),
    ),
  );
}

class DeviceListDrawer extends StatefulWidget {
  @override
  _DeviceListDrawerState createState() => _DeviceListDrawerState();
}

class _DeviceListDrawerState extends State<DeviceListDrawer> {
  @override
  Widget build(BuildContext context) {
    return new Container(
      width: 200.0,
      color: Colors.white,
      child: Column(
        children: <Widget>[
          new Container(
            width: 200.0,
            color: Colors.blue,
            padding: new EdgeInsets.only(
                top: MediaQuery.of(context).padding.top + 16.0, bottom: 16.0),
            child: new Text('demo '),
          ),
          new Expanded(
            child: new ListView(
              children: <Widget>[
                new Text('item 1'),
                new Text('item 2'),
                new Text('item 3'),
              ],
            ),
          ),
          new RaisedButton(
            child: new Text('add item'),
            onPressed: () {},
          )
        ],
      ),
    );
  }
}

Could you please point out what is the problem?你能指出问题是什么吗? And how i can make a layout dynamique?我怎样才能使布局动态化? Thanks for your help.谢谢你的帮助。

you can try你可以试试

Navigator.pop(context, true);

instead of代替

Navigator.pop()

void rebuild(BuildContext context) {
  Navigator.pop(context);
  setState(() {});
}

For new people that run into this, one thing you can do is simply lock the device orientation in portrait mode while the drawer is open.对于遇到这种情况的新手,您可以做的一件事就是在抽屉打开时将设备方向锁定为纵向模式。 This prevents that error.这可以防止该错误。

In my case, I build the app bar and drawer differently depending on screen width (which obviously changes with orientation), and like the OP I only build the drawer with narrow screens (which occurs in portrait mode on smaller devices).在我的例子中,我根据屏幕宽度(这显然随着方向而变化)构建了不同的应用栏和抽屉,并且像 OP 我只构建了窄屏幕的抽屉(在较小的设备上以纵向模式出现)。

 return Scaffold( appBar: _buildAppBar(context), drawer: _buildDrawer(context), body: Beamer( key: _beamerKey, routerDelegate: routerDelegate, ), onDrawerChanged: (isOpened) { // this is a workaround to fix an error that happens if user changes // device orientation while drawer is open. Basically, we lock it // in portrait mode when the drawer is open so it can't be rebuilt // without the drawer by rotating the device. if (isOpened) { // lock orientation to portrait mode while drawer is open SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); } else { // closed, unlock // lock orientation to portrait mode while drawer is open SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight ]); } }, );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 flutter 应用程序中的“setState() 或 MarkNeedsBuild() 调用期间”错误 - “setState() or MarkNeedsBuild() called during” error in flutter app 在构建 TextField 期间调用 setState() 或 markNeedsBuild() - setState() or markNeedsBuild() called during build TextField (在构建过程中出现错误)在构建过程中调用了 setState() 或 markNeedsBuild()。相关的导致错误的小部件是 MaterialApp - (Getting the error while building) setState() or markNeedsBuild() called during build.The relevant error-causing widget was MaterialApp 无限滚动列表视图 - 在构建期间调用的setState()或markNeedsBuild - Infinite Scroll listview - setState() or markNeedsBuild called during build 锁定方向时,听取设备方向更改 - Listen device orientation change when orientation is locked 如何将函数从子类传递到父类,我收到此错误:在构建期间调用了 setState() 或 markNeedsBuild() - How to pass function from a child class to parent class, I am getting this error: setState() or markNeedsBuild() called during build Flutter:使用带有 AnimatedSwitcher 的 setstate 时未重建小部件 - Flutter: Widget not rebuilt when using setstate with AnimatedSwitcher SherlockActionBar在方向更改时被锁定 - SherlockActionBar gets locked on orientation change 屏幕方向更改时未调用加载程序 - Loader not being called when screen orientation change 如果在AsyncTaskLoader运行期间发生方向更改,则不会调用LoaderCallbacks.onLoadFinished - LoaderCallbacks.onLoadFinished not called if orientation change happens during AsyncTaskLoader run
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM