Home > Enterprise >  updating variable async await
updating variable async await

Time:04-22

I want to do simple "translator" on phone, words are sourced from XML file called "test.xml". This is how it looks:

enter image description here

When im typing correct word in my TextField and clicking button, it runs a function getXmlFile() and store it's value in _translatedText2 :

ButtonClass(
    whenClick: () async {
      final _translatedText2 = await getXmlFile(context, _typedText);
      print("value of var where should be translation: $_translatedText2");
       setState(() {
          _typedText = _searchValue.text;
          _translatedText1 = _translatedText2.toString();
       });
         },
       )

This function get's value from test.xml and converting it into List of translated words.

Im pasting getXmlFile() :

Future<List<String>> getXmlFile(BuildContext context, _typedText) async {
  String xmlString =
      await DefaultAssetBundle.of(context).loadString("assets/test.xml");

  var raw = xml.XmlDocument.parse(xmlString);

  var elements = raw.findAllElements(_typedText);

  return elements.map((node) {
    return (node.text);
  }).toList();
}

So, where is problem ???

_translatedText2 has value of translated text, and it's good, but he only acquires it only after second click then i see my translation on screen. It should be right away.

My helpful observation

After first click _translatedText2 is just empty. i Know it because i printed it's value right after getXmlFile() (this print() is in code), it prints out empty List of strings.

As i said, only after second click on button it prints out correct value. That's problem.

ButtonClass (shortened to be more readable):

class ButtonClass extends StatefulWidget {
  ButtonClass({Key? key, required this.whenClick}) : super(key: key);
  VoidCallback whenClick;
  @override
  State<ButtonClass> createState() => _ButtonClassState();
}

class _ButtonClassState extends State<ButtonClass> {
  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
        onPressed: widget.whenClick,
        child: const Icon(
          Icons.translate,
        ));
  }
}

and lastly MyHomePage (shortened to be more readable) :

void main() {
  runApp(const MyApp());
  WidgetsFlutterBinding.ensureInitialized();
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage("text"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage(String text, {Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

final _searchValue = TextEditingController();
String _typedText = "finding txt";
String _translatedText1 = "translation";

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    getXmlFile(context, _typedText);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body:
            Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
          Text(
            "Search Word",
            style: GoogleFonts.overpass(
                fontSize: 40, color: Colors.white, fontWeight: FontWeight.bold),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 104.0),
            child: TextField(
              controller: _searchValue,
              decoration: const InputDecoration(
                prefixIcon: Icon(Icons.search),
                hintText: "Enter Word",
              ),
            ),
          ),
          Center(child: ButtonClass(
            whenClick: () async {
              final _translatedText2 = await getXmlFile(context, _typedText);
              print("wartosc po funkcji:$_translatedText2");
              setState(() {
                _typedText = _searchValue.text;
                _translatedText1 = _translatedText2.toString();
              });
            },
          )),
          Row(mainAxisAlignment: MainAxisAlignment.center, children: [
            Text("finding text::"),
            Text(_typedText,
                textAlign: TextAlign.center,
                style: GoogleFonts.overpass(
                  color: Colors.green,
                ))
          ]),
          Wrap(children: [
            Text("translation:"),
            Text(_translatedText1,
                textAlign: TextAlign.center,
                style: GoogleFonts.overpass(
                  color: Colors.red,
                ))
          ])
        ]));
  }
}


CodePudding user response:

 whenClick: () async {
      final _translatedText2 = await getXmlFile(context, _typedText);
      print("value of var where should be translation: $_translatedText2");
       setState(() {
          _typedText = _searchValue.text;
          _translatedText1 = _translatedText2.toString();
       });
         },

In this block of code, you search for _typedText but only set if after the search is done. So your result is basically always one step behind.

The line should probably read:

final _translatedText2 = await getXmlFile(context, _searchValue.text);
  • Related