Heim  >  Fragen und Antworten  >  Hauptteil

Flutter kann den neuen Wert einer Variablen nicht abrufen, wenn es in einer anderen Klasse aufgerufen wird

Ich habe dieses StatefulWidget, das Daten basierend auf Bedingungen aus der MySQL-Datenbank abrufen und diese abgerufenen Werte einem Array hinzufügen soll, damit ich sie mithilfe der Array-Werte in einer ListView anzeigen kann. Mein Problem ist, dass manchmal, wenn das Array (_fileValues) 和 _custUsername Variable leer oder nicht aktualisiert ist, die Ausnahme nicht ausgelöst wird.

Dies ist mein Stateful-Widget (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 Klasse (Diese Klasse ruft den Benutzernamen aus der Datenbanktabelle basierend auf der E-Mail-Adresse im Textfeld ab)

Wenn ich die Klasse _usernameDetected aus der Klasse UsernameGetter 类打印 _usernameDetected 类时,它返回返回字符串的更新版本,但是当我将 _custUsername 分配给 UsernameValuemain.dart drucke, gibt sie eine aktualisierte Version der zurückgegebenen Zeichenfolge zurück, aber wenn ich _custUsername UsernameValue von zuweise

, es wird nicht aktualisiert und gibt manchmal einen Nullwert zurück.

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

Klasse (Benutzerelementnamen abrufen, der in der Textspalte gespeichert ist)

NameGetter 类,与 UsernameGetter 发生相同的情况。当我从 main.dart 检索值并将值添加到 _fileValuesFür die

-Klasse passiert das Gleiche mit

. Wenn ich den Wert von

abrufe und den Wert zur Liste _fileValues hinzufüge, ist der Wert manchmal leer und manchmal wird der Wert nicht aktualisiert.

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;
  }
}

Ich bin mir nicht sicher, wo meine Fehler liegen, aber ich bin mir ziemlich sicher, dass ich viele davon gemacht habe und ich jemanden brauche, der mir hilft, sie herauszufinden. Insbesondere im Hinblick darauf, warum Listen und Variablen nicht aktualisiert werden/manchmal leer sind.

Referenzlink:

Flutter ListView nicht aktualisiert

Ich habe ein Problem damit, dass meine Liste in Flutter den Code nicht aktualisiert🎜 🎜Warum werden Variablenwerte im Flattern nicht aktualisiert? 🎜
P粉670107661P粉670107661181 Tage vor352

Antworte allen(1)Ich werde antworten

  • P粉521697419

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

    问题

    callData() 方法的精简版本如下所示:

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

    如前文所述,anotherAsyncFunction(foo)someAsyncFunction() 之后、then() 之前 立即调用> 分配 foo 的值。

    您可以通过有策略地插入 print() 语句来亲自观察此行为。

    解决方案

    在底层,Future.then()async/await 是同一件事。然而,当使用async/await时,人们通常更容易推断异步代码的行为,因为这样它读起来就像顺序执行的代码。

    虽然您可以使用其中任何一个,但我建议您转向 async/await 以使代码在阅读时更容易理解。

    以下是如何重构 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());
        });
      }
    

    这样写,很明显 custUsername 是在调用 NameGetter().Connection(custUsername) 之前分配的。

    请务必通读异步编程:futures、async、await

    Antwort
    0
  • StornierenAntwort