Flutter:小部件状态:这段代码安全吗?

Posted

技术标签:

【中文标题】Flutter:小部件状态:这段代码安全吗?【英文标题】:Flutter: Widget State: Is this code safe? 【发布时间】:2019-10-16 09:39:08 【问题描述】:

下面的代码是一个例子来说明这个问题。下面的代码有效,但是下面的行:

class WidgetCustom extends StatefulWidget 

在 vsCode 中有绿色下划线的“WidgetCustom”,当光标放在它上面时,它会显示消息: “这个类(或这个类继承自的一个类)被标记为@immutable,但它的一个或多个实例字段不是最终的”。

代码运行良好。

使用此代码安全吗?

有没有办法在没有警告的情况下实现这一点?

import 'package:flutter/material.dart';

class WidgetCustom extends StatefulWidget 

  _WidgetCustomState _state;

  WidgetCustom(@required int iCount) 
    _state = _WidgetCustomState(iCount);
  

  @override
  State<StatefulWidget> createState() 
    return _state;
  

  int get getIcount => _state.iCount;


class _WidgetCustomState extends State<WidgetCustom> 
  int iCount;

  _WidgetCustomState(this.iCount);

  @override
  Widget build(BuildContext context) 
    return Container(
        child: Row(children: <Widget>[
      Column(
        children: <Widget>[
          RaisedButton(
              child: const Text("Please tap me"),
              onPressed: () 
                setState(() => iCount = iCount + 1);
              ),
          SizedBox(height: 40),
          Text("Tapped $iCount Times")
        ],
      ),
    ]));
  

编辑添加 main.dart

import 'package:flutter/material.dart';
import 'widgetCustom.dart';

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Custom Widget Demo'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  WidgetCustom _widgetCustom;
  String _sMessage = "Fab has not been pressed";
  @override
  void initState() 
    super.initState();
    _widgetCustom = WidgetCustom(iCount: 99);
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(children: [
        _widgetCustom,
        SizedBox(height: 40),
        Text(_sMessage),
      ]),
      floatingActionButton: FloatingActionButton(
        onPressed: _fabPressed,
        tooltip: 'Get Value',
        child: Icon(Icons.add),
      ),
    );
  

  _fabPressed() 
    setState(() => _sMessage =
        "Value from last button click = $_widgetCustom.getIcount");
  


【问题讨论】:

是的,我贴的代码是直接复制的。 您需要将 iCount 声明为类级别变量的最终变量。 我需要 iCount 的当前更新值。 【参考方案1】:

在创建小部件时将初始值作为最终值传递给构造函数,然后从State类中获取。

【讨论】:

【参考方案2】:

更新代码:

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.dark(),
      home: MyHomePage(title: 'Custom Widget Demo'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  WidgetCustom _widgetCustom;
  String _sMessage = "Fab has not been pressed";
  int _value = 99;

  @override
  void initState() 
    super.initState();
    _widgetCustom = WidgetCustom(iCount: _value, function: _update);
  

  void _update(int value) 
    setState(() 
      _value = value;
      _widgetCustom = WidgetCustom(iCount: _value, function: _update);
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Column(
        children: [
          _widgetCustom,
          SizedBox(height: 40),
          Text(_sMessage),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _fabPressed,
        tooltip: 'Get Value',
        child: Icon(Icons.add),
      ),
    );
  

  _fabPressed() 
    setState(() => _sMessage = "Value from last button click = $_value");
  


class WidgetCustom extends StatefulWidget 
  final int iCount;
  final Function function;

  WidgetCustom(@required this.iCount, this.function);

  @override
  State<StatefulWidget> createState() 
    return _WidgetCustomState();
  


class _WidgetCustomState extends State<WidgetCustom> 
  int _iCount;

  @override
  void initState() 
    super.initState();
    _iCount = widget.iCount;
  

  @override
  Widget build(BuildContext context) 
    return Container(
      child: Row(
        children: <Widget>[
          Column(
            children: <Widget>[
              RaisedButton(child: const Text("Please tap me"), onPressed: ()
                _iCount = _iCount + 1;
                widget.function(_iCount);
              ),
              SizedBox(height: 40),
              Text("Tapped $_iCount Times")
            ],
          ),
        ],
      ),
    );
  

【讨论】:

关键部分是“int getIcount => _state.iCount;”我需要能够获得价值。 你可以做int get getIcount =&gt; iCount; 我添加了 main.dart 以便更好地说明。 @BrianOh 您正在寻找结合@CopsOnRoad 方法的didUpdateWidget 生命周期。 @BrianOh 我昨天没时间,反正我刚刚更新了代码,它正在工作。

以上是关于Flutter:小部件状态:这段代码安全吗?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter/Dart:我的小部件树中可以有多个带有状态的小部件吗?

从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter

在 Flutter 中使用 BLoC - 在有状态小部件与无状态小部件中的使用

Flutter:从子 StreamBuilder 更新有状态小部件

Flutter BLoC - 状态不会触发小部件重建

从原生 Android 主屏幕小部件调用 Flutter (Dart) 代码