Flutter ne peut pas obtenir la nouvelle valeur d'une variable lorsqu'il est appelé dans une autre classe
P粉670107661
P粉670107661 2024-04-01 22:37:38
0
1
497

J'ai ce StatefulWidget qui est censé récupérer les données de la base de données MySQL en fonction des conditions et ajouter ces valeurs récupérées à un tableau afin que je puisse les afficher sur un ListView en utilisant les valeurs du tableau. Mon problème est que parfois lorsque le tableau (_fileValues) 和 _custUsername variable est vide ou n'est pas mis à jour, l'exception n'est pas levée.

Voici mon widget avec état (main.dart)

String? _custUsername;
List<String> _fileValues = <String>[];

class cakeLogin extends StatefulWidget {
  @override
  cakeLoginPageMain createState() => cakeLoginPageMain(); 
}

class cakeLoginPageMain extends State<cakeLogin> {

  String? _CustEmailInit; 
  BuildContext? loginContext;

  List<String> _fileNameStores = <String>[];

  void callData() {
    // @ Get username based on user email and assign it to _custUsername variable
    UsernameGetter().Connection(_CustEmailInit!).then((UsernameValue) {
      _custUsername = UsernameValue!;
    });
    
    // @ Get item names based on the user username (_custUsername) and add them into
    // _fileNameStores
    NameGetter().Connection(_custUsername).then((NamesValues) {
      for(var _nameItems in NamesValues) {
        setState(() {
          _fileNameStores.add(_nameItems);
        });
      }
    });
    // @ Remove duplicates value and add them into main list (_fileValues)
    var _removeDuplicates = _fileNameStores.toSet().toList();
    for(var item in _removeNamesDupes) {
      setState(() {
       _fileValues.add(item);
      });
     }

  }
  
  @override
  Widget build(BuildContext context) {

    final _emailController = TextEditingController();

    return Scaffold(
      appBar: AppBar(
        title: Text("Login to App",
          style: TextStyle(
            fontSize: 18,
            color: setupFontCol,
            fontWeight: FontWeight.bold
          )),
        backgroundColor: setupThemeBar,
        centerTitle: true,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(20),
        )
      ),
      backgroundColor: setupMainTheme,
      body: Padding(
        padding: EdgeInsets.all(20),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextFormField(
              controller: _emailController,
              style: TextStyle(color: Color.fromARGB(255, 214, 213, 213)),
              decoration: InputDecoration(
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                filled: true,
                hintStyle: TextStyle(color: Color.fromARGB(255, 197, 197, 197)),
                hintText: "Enter your email",
                fillColor: setupThemeBar
              ),
            ),

           SizedBox(height: 18),

           SizedBox(height: 25),

          SizedBox(
            height: 45,
            width: 500,
            child: ElevatedButton(
              style: 
                ElevatedButton.styleFrom(
                  primary: setupFontCol,
                  onPrimary: Colors.white,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                  )
                ),
              onPressed: () {

                var _CustEmail = _emailController.text;

                if(_CustEmail.contains("@gmail.com") || _CustEmail.contains("@email.com")) {
                   if(_CustEmail != "") {
                          _CustEmailInit = _CustEmail;
                          loginContext = context;

                          _isFromLogin = true;
  
                          _fileValues.clear();
                          callData();

                    } else {
                      alertDialog("Please enter your email address",context);
                    }
                } else {
                    alertDialog("Email address is not valid",context);
                }
              },
              //color: setupFontCol,
              child: Text("Login",
                style: TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.normal,
                  fontSize: 14,
                ))
              ),
            ),
          ],
        ),
      ),      
    );
  }
}

UsernameGetter Classe (Cette classe récupérera le nom d'utilisateur de la table de base de données en fonction de l'e-mail saisi dans le champ de texte)

Lorsque j'imprime la classe _usernameDetected à partir de la classe UsernameGetter 类打印 _usernameDetected 类时,它返回返回字符串的更新版本,但是当我将 _custUsername 分配给 UsernameValuemain.dart, elle renvoie une version mise à jour de la chaîne renvoyée, mais lorsque j'attribue _custUsername à UsernameValue de

, il ne se met pas à jour et renvoie parfois une valeur nulle.

import 'package:mysql_client/mysql_client.dart';
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';
import 'package:signuppage/main.dart' as main;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class UsernameGetter {
  Future<String> Connection(String _custEmail) async {
    final conn = await MySQLConnection.createConnection(
      host: "",
      port: ,
      userName: "",
      password: "",
      databaseName: "",
    );

    await conn.connect();

    var _getUsernameQue = await conn.execute("SELECT CUST_USERNAME FROM information WHERE CUST_EMAIL = :email", 
    {
      "email": _custEmail
    });

    String? _usernameDetected;
    for(final _rowsOfEmail in _getUsernameQue.rows) {
      _usernameDetected = _rowsOfEmail.assoc()['CUST_USERNAME']!;
    }
    return await _usernameDetected!;
  }
}
NameGetter

classe (récupère le nom de l'élément utilisateur stocké dans la colonne de texte)

NameGetter 类,与 UsernameGetter 发生相同的情况。当我从 main.dart 检索值并将值添加到 _fileValuesPour la classe

, la même chose se produit avec

. Lorsque je récupère la valeur de

et que j'ajoute la valeur à la liste _fileValues, parfois la valeur est vide et parfois la valeur n'est pas mise à jour.

import 'package:mysql_client/mysql_client.dart';
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';
import 'package:signuppage/main.dart' as main;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class NameGetter {

  Future<List<String>> Connection(String _custUsername) async {
    final conn = await MySQLConnection.createConnection(
      host: "",
      port: ,
      userName: "",
      password: "",
      databaseName: "",
    );
    await conn.connect();

    var _getItemNames= await conn.execute("SELECT ITEM_NAMES FROM item_details WHERE CUST_USERNAME = :username",
      {
        "username": _custUsername
      });

    List<String>? _itemNamesValues= <String>[]; 
    for(var _rowsOfItemNames in _getItemNames.rows) {
      var _retrieveNames = await _rowsOfItemNames.assoc()['ITEM_NAMES']!;
      _itemNamesValues.add(_retrieveNames);
    }

    return await _itemNamesValues;
  }
}

Je ne sais pas où sont mes erreurs, mais je suis presque sûr d'en avoir fait beaucoup et j'ai besoin de quelqu'un pour m'aider à les comprendre. Surtout en ce qui concerne la raison pour laquelle les listes et les variables ne sont pas mises à jour/parfois vides.

Lien de référence :

Flutter ListView non mis à jour

J'ai un problème avec ma liste dans Flutter qui ne met pas à jour le code🎜 🎜Pourquoi les valeurs des variables ne sont-elles pas actualisées dans Flutter ? 🎜
P粉670107661
P粉670107661

répondre à tous(1)
P粉521697419

Question

callData() Une version simplifiée de la méthode ressemble à ceci :

  var foo;

  void callData() {
    someAsyncFunction().then( ... foo = value ... );
    anotherAsyncFunction(foo).then( ... );
  }

Comme mentionné précédemment, la valeur de anotherAsyncFunction(foo)someAsyncFunction() 之后、then() 之前 立即调用> 分配 foo.

Vous pouvez observer ce comportement vous-même en insérant stratégiquement des déclarations print().

Solution

Sous le capot, il est souvent plus facile pour les gens de déduire le comportement d'un code asynchrone lorsque Future.then()async/await 是同一件事。然而,当使用async/await il se lit comme du code exécuté séquentiellement.

Bien que vous puissiez utiliser n'importe lequel d'entre eux, je vous recommande de vous tourner vers async/await pour rendre le code plus facile à comprendre lors de la lecture.

Voici un exemple de refactorisation callData() :

  Future callData() async {
    // @ Get username based on user email and assign it to _custUsername variable
    var custUsername = await UsernameGetter().Connection(_CustEmailInit!);
    
    // @ Get item names based on the user username (_custUsername) and add them into
    // _fileNameStores
    var namesValues = await NameGetter().Connection(custUsername);

    setState(() {
      _fileNameStores.addAll(namesValues);
      // @ Remove duplicates value and add them into main list (_fileValues)
      _fileValues.addAll(_fileNameStores.toSet());
    });
  }

Écrit ainsi, il est évident que custUsername 是在调用 NameGetter().Connection(custUsername) a été attribué auparavant.

Assurez-vous de lire Programmation asynchrone : futures, async, wait.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal