recherche

Maison  >  Questions et réponses  >  le corps du texte

Flutter ne peut pas obtenir la nouvelle valeur d'une variable lorsqu'il est appelé dans une autre classe

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粉670107661P粉670107661230 Il y a quelques jours452

répondre à tous(1)je répondrai

  • P粉521697419

    P粉5216974192024-04-02 09:09:07

    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.

    répondre
    0
  • Annulerrépondre