Flutter Widget不刷新问题

Stella981
• 阅读 719
import 'package:flutter/material.dart';

/// 温度显示 -- ok
class TemperatureIndication extends StatefulWidget {
  final ValueChanged<int> valueChanged;
  final int choosedItem;

  TemperatureIndication({this.valueChanged, this.choosedItem = 0});

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

class _TemperatureIndicationState extends State<TemperatureIndication> {
  int _choosedItem = 0;

  @override
  void initState() {
    super.initState();   // 错误点在这里
    _choosedItem = widget.choosedItem;
    print('_TemperatureIndicationState initState:$_choosedItem');
  }

  @override
  Widget build(BuildContext context) {
//    _choosedItem = widget.choosedItem;
//    print('_TemperatureIndicationState build:$_choosedItem');
    return _buildItem();
  }

  Widget _buildItem() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 32.0),
      child: Column(
        children: <Widget>[
          _buildTextItem(),
          Padding(padding: const EdgeInsets.only(top: 4.0)),
          _buildButtonItem(),
        ],
      ),
    );
  }

  Widget _buildTextItem() {
    return Row(
      children: <Widget>[
        Expanded(
          child: Center(child: Text('切')),
        ),
        Expanded(
          child: Center(child: Text('低')),
        ),
        Expanded(
          child: Center(child: Text('中')),
        ),
        Expanded(
          child: Center(child: Text('高')),
        ),
      ],
    );
  }

  Widget _buildButtonItem() {
    return DecoratedBox(
      decoration: BoxDecoration(border: Border.all(width: 1.5, color: Color(0xffd6def1))),
      child: Row(
        children: <Widget>[
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                _choosedItem = 0;
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(0);
                }
              },
              child: DecoratedBox(
                decoration: _choosedItem == 0
                    ? BoxDecoration(
                        color: Colors.grey,
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                _choosedItem = 1;
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(1);
                }
              },
              child: DecoratedBox(
                decoration: _choosedItem == 1
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                _choosedItem = 2;
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(2);
                }
              },
              child: DecoratedBox(
                decoration: _choosedItem == 2
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                _choosedItem = 3;
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(3);
                }
              },
              child: DecoratedBox(
                decoration: _choosedItem == 3
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

测试代码:

@override
  Widget build(BuildContext context) {
    print('父类build问题:$chooseItem');
    return Scaffold(
      appBar: AppBar(),
      body: TemperatureIndication(
        valueChanged: (i) {
          chooseItem = i;
          print('点击选中的值:$chooseItem');
          chooseItem = 0;
          print('强制更改的值:$chooseItem');
          setState(() {});
        },
        choosedItem: chooseItem,
      ),
    );
  }

简单功能:就是把选中的值返回给调用者

Flutter Widget不刷新问题

问题描述:在返回值函数里,强制把选中的值改为 0,发现没有效果?

结论:按照官网的文档说法,widget会由架构来判断是否会刷新,判断会刷新了才刷新。刚好,我这种写法是被判断为不刷新。

@override
  void initState() {
    super.initState();
    _choosedItem = widget.choosedItem;
    print('_TemperatureIndicationState initState:$_choosedItem');
  }

问题出在以上代码中。我在State类重新定义了一个属性在initState函数中接收StatefulWidget的属性,导致的出现这样子的问题。

正确的做法是在State的build方法中直接使用StatefulWidget的属性。即是widget.choosedItem在build方法中直接使用。

原因:State的initState只执行了一次,后面StatefulWidget的choosedItem更改了,但是没有再次执行initState方法,导致_choosedItem没有跟着更改。所以界面就不会跟着更改。

结论:StatefulWidget是State的配置文件,在State中直接使用StatefulWidget的属性。

以上代码改为:

import 'package:flutter/material.dart';

/// 温度显示 -- ok
class TemperatureIndication extends StatefulWidget {
  final ValueChanged<int> valueChanged;
  final int choosedItem;

  TemperatureIndication({this.valueChanged, this.choosedItem = 0});

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

class _TemperatureIndicationState extends State<TemperatureIndication> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return _buildItem();
  }

  Widget _buildItem() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 32.0),
      child: Column(
        children: <Widget>[
          _buildTextItem(),
          Padding(padding: const EdgeInsets.only(top: 4.0)),
          _buildButtonItem(),
        ],
      ),
    );
  }

  Widget _buildTextItem() {
    return Row(
      children: <Widget>[
        Expanded(
          child: Center(child: Text('切')),
        ),
        Expanded(
          child: Center(child: Text('低')),
        ),
        Expanded(
          child: Center(child: Text('中')),
        ),
        Expanded(
          child: Center(child: Text('高')),
        ),
      ],
    );
  }

  Widget _buildButtonItem() {
    return DecoratedBox(
      decoration: BoxDecoration(border: Border.all(width: 1.5, color: Color(0xffd6def1))),
      child: Row(
        children: <Widget>[
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(0);
                }
              },
              child: DecoratedBox(
                decoration: widget.choosedItem == 0
                    ? BoxDecoration(
                        color: Colors.grey,
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(1);
                }
              },
              child: DecoratedBox(
                decoration: widget.choosedItem == 1
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(2);
                }
              },
              child: DecoratedBox(
                decoration: widget.choosedItem == 2
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
          Expanded(
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                setState(() {});
                if (widget.valueChanged != null) {
                  widget.valueChanged(3);
                }
              },
              child: DecoratedBox(
                decoration: widget.choosedItem == 3
                    ? BoxDecoration(
                        color: Color(0xfffe0007),
                      )
                    : BoxDecoration(),
                child: Container(
                  height: 28.0,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
点赞
收藏
评论区
推荐文章
顺心 顺心
3年前
可以用Flutter愉快的开发web 了
简单的试了一下,完全用flutter现有的widget进行开发。github上面有说现在是preview版本,有些widget还不能用。但是最终是会支持整个的flutter现有的UI的。跟用flutter开发原生app一样。flutter_web还有很长的一段路要走。希望年底能出个像样的版本。不支持第三方库说明目前pub.da
Stella981 Stella981
2年前
Flutter学习之动态ListView
import'package:flutter/material.dart';voidmain(){runApp(listname(item:newList<String.generate(1000,(i)"genarate$i")));}
Stella981 Stella981
2年前
Flutter
在Flutter加载网页?也是有WebView的哦,和Android一样1.添加依赖dependencies:flutter\_webview\_plugin:^0.2.122.导入库import'import'package:flutter\_webview\_plugin/flutter\_webview\_plug
Stella981 Stella981
2年前
Flutter中日期组件DatePicker及组件汉化
Flutter提供了DatePicker组件进行时间选择。日期组件及时间组件代码示例:import'package:flutter/material.dart';//第三方插件,需要提前配置import'package:date_format/date_format.dart';classDat
Stella981 Stella981
2年前
Flutter 页面入栈和出栈
Docs(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fdocs.flutter.io%2Fflutter%2Fwidgets%2FNavigatorclass.html)demoimport'package:flutter/material.dart';
Stella981 Stella981
2年前
Flutter学习之重叠布局
1.两个元素的重叠布局可以使用stack组件import'package:flutter/material.dart';voidmain(){runApp(MyApp());}classMyAppextendsStatelessWidget{
Stella981 Stella981
2年前
Flutter入门(四)
\TabBar(顶部导航)import'package:flutter/material.dart';classCategoryPageextendsStatefulWidget{CategoryPage({Keykey}):super(key:key);@o
Stella981 Stella981
2年前
Flutter BottomSheet底部弹窗效果
BottomSheet是一个从屏幕底部滑起的列表(以显示更多的内容)。你可以调用showBottomSheet()或showModalBottomSheet弹出import'package:flutter/material.dart';import'dart:async';classBottomSheetDem
Stella981 Stella981
2年前
Flutter 基础组件:文本、字体样式
//文本、字体样式import'package:flutter/material.dart';classTextFontStyleextendsStatelessWidget{//声明文本样式TextStyletextStyleconstT
Stella981 Stella981
2年前
34 Flutter仿京东商城项目 用户注册 注册流程 POST发送验证码 倒计时功能 验证验证码
加群_452892873_下载对应34课文件,运行方法,建好项目,直接替换lib目录以下列出的是本课涉及的文件。RegisterFirst.dartimport'package:flutter/material.dart';import'package:flutter_jdshop/services/ScreenA