【问题标题】:dart/flutter: Variable wrapped in ValueNotifier doesn't updatedart/flutter:包装在 ValueNotifier 中的变量不会更新
【发布时间】:2022-12-19 22:51:34
【问题描述】:

我正在 Flutter 中创建一个翻译应用程序。我在文件currentLang.dart 中创建了一个类CurrentLanguages

// currentLang.dart

import 'package:vtranslate/models/lang.dart';
import 'package:flutter/material.dart';

class CurrentLanguages extends ChangeNotifier {
  ValueNotifier<Lang> sourceLang =
      ValueNotifier<Lang>(Lang('English', 'en', false));
  ValueNotifier<Lang> outputLang =
      ValueNotifier<Lang>(Lang('French', 'fr', false));

  changeSource(Lang language) {
    sourceLang.value = language;
    notifyListeners();
  }

  changeOutput(Lang language) {
    outputLang.value = language;
    notifyListeners();
  }
}

在另一个屏幕 language-pages.dart 中,我有一个自定义列表元素,它有一个调用函数 _sendBackLanguageonSelect 函数。此函数采用语言参数,并使用函数changeSource()changeOutput() 设置 sourceLang/outputLang 的值

但是,如果我们打印 CurrentLanguages().sourceLang.value.name 的值(与 outputLang 相同)=> 变量不会更新并且显示的内容与调用 changeSource/changeOutput 函数之前相同(即英语和法语)

// language-pages.dart
import 'package:flutter/material.dart';
import 'package:vtranslate/components/lang-list-element.dart';
import 'package:vtranslate/models/lang.dart';
import 'package:vtranslate/helper/currentLang.dart';

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

  final String title;

  @override
  State<LangPage> createState() => _LangPageState();
}

class _LangPageState extends State<LangPage> {
  final List<Lang> _langList = [
    Lang('Afrikaans', 'af', false),
    Lang('Arabic', 'ar', false),
    Lang('Belarusian', 'be', false),
    Lang('Bulgarian', 'bg', false),
    Lang('Bengali', 'bn', false),
    Lang('Catalan', 'ca', false),
    Lang('Czech', 'cs', false),
    Lang('Welsh', 'cy', false),
    Lang('Danish', 'da', false),
    Lang('German', 'de', false),
    Lang('Greek', 'el', false),
    Lang('English', 'en', false),
    Lang('Esperanto', 'eo', false),
    Lang('Spanish', 'es', false),
    Lang('Estonian', 'et', false),
    Lang('Persian', 'fa', false),
    Lang('Finnish', 'fi', false),
    Lang('French', 'fr', false),
    Lang('Irish', 'ga', false),
    Lang('Galician', 'ga', false),
    Lang('Gujarati', 'gu', false),
    Lang('Hebrew', 'he', false),
    Lang('Hindi', 'hi', false),
    Lang('Croatian', 'hr', false),
    Lang('Haitian', 'ht', false),
    Lang('Hungarian', 'hu', false),
    Lang('Indonesian', 'id', false),
    Lang('Icelandic', 'is', false),
    Lang('Italian', 'it', false),
    Lang('Japanese', 'ja', false),
    Lang('Georgian', 'ka', false),
    Lang('Kannada', 'kn', false),
    Lang('Korean', 'ko', false),
    Lang('Lithuanian', 'lt', false),
    Lang('Latvian', 'lv', false),
    Lang('Macedonian', 'mk', false),
    Lang('Marathi', 'mr', false),
    Lang('Malay', 'ms', false),
    Lang('Maltese', 'mt', false),
    Lang('Dutch', 'nl', false),
    Lang('Norwegian', 'no', false),
    Lang('Polish', 'pl', false),
    Lang('Portuguese', 'pt', false),
    Lang('Romanian', 'ro', false),
    Lang('Russian', 'ru', false),
    Lang('Slovak', 'sk', false),
    Lang('Slovenian', 'sl', false),
    Lang('Albanian', 'sq', false),
    Lang('Swedish', 'sv', false),
    Lang('Swahili', 'sw', false),
    Lang('Tamil', 'ta', false),
    Lang('Telugu', 'te', false),
    Lang('Thai', 'th', false),
    Lang('Tagalog', 'tl', false),
    Lang('Turkish', 'tr', false),
    Lang('Ukranian', 'uk', false),
    Lang('Urdu', 'ur', false),
    Lang('Vietnamese', 'vi', false),
    Lang('Chinese', 'zh', false),
  ];

  _sendBackLanguage(Lang returnedLanguage) {
    // if (this.widget.title == "Source Language") {
    //   setState(() {
    //     CurrentLanguages.sourceLang = returnedLanguage;
    //   });
    // } else if (this.widget.title == "Translation Language") {
    //   setState(() {
    //     CurrentLanguages.outputLang = returnedLanguage;
    //   });
    // } else {
    //   throw Error();
    // }

    if (this.widget.title == "Source Language") {
      CurrentLanguages().changeSource(returnedLanguage);
    } else if (this.widget.title == "Translation Language") {
      CurrentLanguages().changeOutput(returnedLanguage);
    } else {
      throw Error();
    }

    Navigator.pop(context);
    print(CurrentLanguages().sourceLang.value.name);
    print(CurrentLanguages().outputLang.value.name);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.widget.title),
        centerTitle: true,
      ),
      body: ListView.builder(
        padding: const EdgeInsets.all(8.0),
        itemCount: _langList.length,
        itemBuilder: (BuildContext context, int index) {
          return LangListElement(
              language: _langList[index], onSelect: _sendBackLanguage);
        },
      ),
    );
  }
}

请告知我犯了什么错误,因为这是我最初的几个应用程序之一。

完整的源代码可以在 DEV 分支中找到:https://github.com/AaravHattangadi/vTranslate/tree/dev

【问题讨论】:

  • 每次你调用CurrentLanguages()你都在创建一个新实例
  • @Ivo 感谢您指出这一点 - 但是,使用 CurrentLanguages.sourceLang.value 访问变量会出现错误 Instance member 'sourceLang' can't be accessed using static access
  • 因为那不是您应该使用它的方式。我建议你阅读docs.flutter.dev/development/data-and-backend/state-mgmt/simple
  • @Ivo 谢谢 - 我现在已经解决了变量更新问题 - 我只需要将 CurrentLanguages() 类中的变量设为静态变量。谢谢!

标签: flutter dart state-management


【解决方案1】:

我通过将 CurrentLanguages 类中的变量设为静态来修复我的错误。谢谢伊沃。

import 'package:vtranslate/models/lang.dart';
import 'package:flutter/material.dart';

class CurrentLanguages extends ChangeNotifier {
  static ValueNotifier<Lang> sourceLang =
      ValueNotifier<Lang>(Lang('English', 'en', false));
  static ValueNotifier<Lang> outputLang =
      ValueNotifier<Lang>(Lang('French', 'fr', false));

  changeSource(Lang language) {
    sourceLang.value = language;
    notifyListeners();
  }

  changeOutput(Lang language) {
    outputLang.value = language;
    notifyListeners();
  }
}

【讨论】:

    猜你喜欢
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2021-11-14
    • 2021-07-04
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    相关资源
    最近更新 更多