Home > Net >  setState deosn't show changes correctly on UI
setState deosn't show changes correctly on UI

Time:03-12

Whenever I click Run Query button I get the expected result in the terminal but I have to click it once again to be able to display the result in the UI!

I guess there is something wrong in setState usage. May you please help me to find out what's wrong?

PS. I tried to use both suggested cases of setState mentioned in this post but I always get the same result.

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MySQL Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'MySQL Test'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  String? _barcode;
  late bool visible;

  @override
  var Connection;
  String? res;

  void initsql() async {
    try {
      var settings = ConnectionSettings(
          host: '127.0.0.1',
          port: 3306,
          user: 'root',
          db: 'testo',
          password: '1234',
          timeout: Duration(minutes: 2));
      Connection = await MySqlConnection.connect(settings);
      print("Connected");
    } catch (e) {
      print(e);
    }
  }

  void getResult() async {
    var results = await Connection.query('SELECT id, Name FROM testo.mytable');
    for (var row in results) {
      res = 'ID: ${row[0]}, Name: ${row[1]}'; //---> Needs Double click!
      print('ID: ${row[0]}, Name: ${row[1]}');
    }
  }

  void initState() {
    initsql();
    super.initState();
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              res == null ? 'Disconnected!' : '$res',
              style: Theme.of(context).textTheme.headline5,
            ),
            Padding(
              padding: const EdgeInsets.all(15.0),
              child: Column(
                children: [
                  ElevatedButton(
                      onPressed: () => setState(() {
                            //---> Needs Double click!!
                            getResult();
                          }),
                      child: Center(child: Text('Run Query'))),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

CodePudding user response:

First of all your getResult method is asynchronous, so the return type is not void but Future<void>.

  Future<void> getResult() async {
    var results = await Connection.query('SELECT id, Name FROM testo.mytable');
    for (var row in results) {
      res = 'ID: ${row[0]}, Name: ${row[1]}'; //---> Needs Double click!
      print('ID: ${row[0]}, Name: ${row[1]}');
    }
  }

The reason why you UI doesn't update the widget on your first tap is, that your getResult is asynchronous. In your button you call setState, which triggers a rebuild of your widget, but since the method is asynchronous, it cannot provide a result immediately when it is started. This means you call setState, it updates your UI, then your method retrieves the new value of getResult, but the UI got updated before that. To fix this you have to wait for your method until it has finished and then call setState to update your UI.

ElevatedButton(
      onPressed: () async {
        await getResult();
        setState((){});
      } ,
      child: Center(
        child: Text('Run Query'),
      ),
    );
  • Related