2

The code below is an example to illustrate this question. The code below works, however the following line:

class WidgetCustom extends StatefulWidget {

has "WidgetCustom" underlined in green in vsCode, and when the cursor is positioned over it, it shows the message: "This class (or a class this class inherits from) is marked as @immutable, but one or more of its instance fields are not final".

The code works fine.

Is it safe to use this code?

Is there a way to achieve this without the warning?

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")
        ],
      ),
    ]));
  }
}

Edited to add 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}");
  }
}

Brian Oh
  • 9,604
  • 12
  • 49
  • 68

2 Answers2

0

Updated code:

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")
            ],
          ),
        ],
      ),
    );
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
0

Pass the initial value to the constructor when creating the widget as a final value, and then get it from the State class.

Brian Oh
  • 9,604
  • 12
  • 49
  • 68