Search code examples
flutterdartsetstate

Updating a widget and issue with setStat


I am currently working on this tutorial in which transfers a variable "myVariable" an external file to another. Link: https://dev.to/lucianojung/global-variable-access-in-flutter-3ijm

I modified my code so that the variable "myVariable" is usable in the myservice.dart file, it works, but the problem is that I cannot dynamically update my text widget "widget.myVariable", it updates only when I do a "hot reaload" I think we should add a setStat, but I do not know how to implement it despite several attempts.

Thanks for your help

myservice.dart

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

class MyService extends StatefulWidget {
  //Passed 'myVariable' ///////////////////////////////////////////////////
  static final MyService _instance = MyService._internal();
  // passes the instantiation to the _instance object
  factory MyService() => _instance;
  //initialize variables in here
  MyService._internal() {
    _myVariable = 0;
  }
  int _myVariable;
  //short getter for my variable
  int get myVariable => _myVariable;
  //short setter for my variable
  set myVariable(int value) => myVariable = value;
  void incrementMyVariable() => _myVariable++;
  /////////////////////////////////////////////////////
  @override
  _MyServiceState createState() => _MyServiceState();
}

class _MyServiceState extends State<MyService> {

  /* i try this but no result
   _displayCounter() {
     setState(() {
       widget.myVariable;
     });
   }
*/
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      width: 250,
      height: 90,
      child: Text(
        // '${_displayCounter()}',
        '${widget.myVariable}',
      ),
    );
  }
}

main.dart

import 'package:flutter/material.dart';
import 'myservice.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: 'Flutter Service Demo App'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  MyService _myService = MyService();
  _incrementCounter() {
    setState(() {
      _myService.incrementMyVariable();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            MyService(), //myservice.dart
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Solution

  • We use a singleton when we need to manage a shared resource. You can read more here.

    What you are trying here, is to use the singleton class as a 'widget'.

    It is evident that you are trying to use myVariable. Perhaps you can make a separate widget that meets this requirement.

    1 -> Edit main.dart : I will make use of _myService object and pass it to Service() where it is supposed to show the count.

    children: <Widget>[ 
      Text( 
       'You have pushed the button this many times:',
      ),
    
     /* Now because of setState(), the build method will be called
        as many times as the counter increases, which will call
        Service() with the MyService instance below
      */ 
    
    Service(_myService), //  ------ service_widget.dart 
    ]
    

    2 -> Leave myservice.dart as it is (as given in the tutorial).

    3 -> service_widget.dart will be as follows:

    import 'package:flutter/material.dart';
    import './myservice.dart';
    
    class Service extends StatelessWidget {
    
    final MyService myService; 
    Service(this.myService); // making use of MyService instance
    
    @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.yellow,
        width: double.infinity,
        child: Text(
          '${myService.myVariable}', // Access myVariable here
           textAlign: TextAlign.center,
           style: TextStyle(
             fontSize: 25,
             fontWeight: FontWeight.bold,
            ),
          ),
        );
      }
    }  
    

    Flutter App - Counter of Clicks

    Now it works fine!

    Though you can see the full code here, I highly recommend you play around some more.

    1. main.dart

    2. myservice.dart

    3. service_widget.dart