7

I managed to pass Stateful class variables' values to the State class through constructor like below:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Demo',
        home: MyHomePage('John', 'Morison'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage(this.fname, this.lname);

  final String fname;
  final String lname;

  @override
  _MyHomePageState createState() => _MyHomePageState(fname, lname);
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState(this.fname, this.lname);

  final String fname;
  final String lname;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Hello $fname $lname'),
      )
    );
  }
}

That's weird and I had to do lot of work as there is more than two variables. Is there a better way?

3 Answers 3

15

Yes, there is widget:

From Doc:

  /// The current configuration.
  ///
  /// A [State] object's configuration is the corresponding [StatefulWidget]
  /// instance. This property is initialized by the framework before calling
  /// [initState]. If the parent updates this location in the tree to a new
  /// widget with the same [runtimeType] and [Widget.key] as the current
  /// configuration, the framework will update this property to refer to the new
  /// widget and then call [didUpdateWidget], passing the old configuration as
  /// an argument.
  T get widget => _widget;
  T _widget;

Code should look like below:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Demo',
        home: MyHomePage('John', 'Morison'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage(this.fname, this.lname);

  final String fname;
  final String lname;

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

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Hello ${widget.fname} ${widget.lname}'),
      )
    );
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

I don't understand this at all. You're storing the state in the widget, and storing the UI build in the state. That's completely backwards to how the objects are named.
1

You can access your variables by widget. like widget.myVariable in the state class. however, it's the best practice to pass the variables to the state class constructor if you want to change them in the state class. remember that the variable must be defined as final in the parent (stateful) class, so if you want to change these variables you must define non-final variables in the state class and initiate their values by the constructor.

  class RecordPage extends StatefulWidget {
      final int myvVariable;
      RecordPage({required this.myvVariable});

      @override
      _RecordPageState createState() => new _RecordPageState(myStateVariable: myvVariable);
  }

class _RecordPageState extends State<RecordPage> {
  int myStateVariable;
  _RecordPageState({required this.myStateVariable});
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          "your initiating variable is " + widget.myvVariable.toString(),
        ),
        Text(
          "your state variable is " + myStateVariable.toString(),
        ),
        InkWell(
          onTap: (){
            setState(() {
              myStateVariable++;
            });
          },
          child: new Container(
            child: Center(
              child: new Text(
                "increase the variable",
              ),
            ),
          ),
        )
      ],
    );
  }
}

3 Comments

You mention "best practice to pass the variables to the state class constructor", however flutter gives me a warning, "Don't put any logic in 'createState'. Try moving the logic out of 'createState'. So, is this really best practice? Either I'm misunderstanding you, or Flutter disagrees with you.
@devklick You're wrong. I said constructor of the class not createState method.
I'm not. The createState method is what apparently "contains logic" by passing arguments to the State classes constructor. See this SO post which highlights the issue, contains links to the docs regarding the issue, and suggests an alternative approach to avoid the issue.
0

There is also a solution with not using the constructor provided in the Flutter Cookbook: https://docs.flutter.dev/cookbook/navigation/passing-data

The idea is using RouteSettings und ModalRoute; here the important code parts:

class _TodosScreenState extends State<TodosScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(

// ...            

    onTap: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => const DetailScreen(),
                      // Pass the arguments as part of the RouteSettings. The DetailScreen reads the arguments from these settings.
                      
                      settings: RouteSettings(
                        
                     // widget. is important to access the variable of the stateful class TodosScreen
                        arguments: widget.todos[index],

// ...

class _DetailScreenState extends State<DetailScreen> {
  
  @override
  Widget build(BuildContext context) {
  
    // must be inside build method, as here is the context parameter available 

    final todo = ModalRoute.of(context)!.settings.arguments as Todo;

   // accessing the variable as u wish
   Text(todo.title)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.