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

时间:2018-06-28 19:30:13

标签: android dart flutter drawer flutter-layout

我想创建一个可以根据设备方向更新UI的App。在Portait布局中,我使用抽屉显示一些元素(Fig.)。在“横向”布局中,没有抽屉,但是元素显示在屏幕左侧的一列(Fig.)中。该程序在抽屉关闭时起作用。

但是,当我打开抽屉将方向从纵向转换为横向时,我收到了“锁定小部件树时调用setState()或markNeedsBuild()”的错误消息 堆栈提供了以下信息:

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.

我在Appbar(Fig.)的开头有一个返回按钮。

这是我的代码:

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: () {},
          )
        ],
      ),
    );
  }
}

能否请您指出问题所在?以及如何进行布局动态化?感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您可以尝试

Navigator.pop(context,true);

代替

Navigator.pop()

最诚挚的问候。

答案 1 :(得分:0)

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