当前位置: 首页 > 知识库问答 >
问题:

flutter ChangeNotifier页面间触发问题?

邬阳
2023-09-13

我在根实例上写了监听代码appModel!.addListener,在一个子页面中进行触发notifyListeners的操作,但addListener中的函数并未执行,为什么呀?

代码如下:
根页面

class MyApp extends StatefulWidget {  @override  MyAppState createState() => MyAppState();}class MyAppState extends State<MyApp> {  AppModel? appModel;  @override  void initState() {    super.initState();    Future.delayed(Duration.zero, () {      appModel = Provider.of<AppModel>(context, listen: false);      appModel!.addListener(() {        print("change ${appModel!.localeCode}");//并未触发      });    });  }// This widget is the root of your application.  @override  Widget build(BuildContext context) {    GlobalProperty.appContext = context;    // print(ChinaDataArea.data);    // print("asd:");    // print(ChinaDataArea.codeToText("710110"));    return GetMaterialApp(      debugShowCheckedModeBanner: false,      title: MConfig.NAME,      theme: themeData,      home: const SplashPage(),      // home: const TabPage(),      // routes: MRouter.routes,      getPages: Pages.pages,      navigatorKey: GlobalProperty.navigatorKey,      locale: Locale(appModel == null ? "en" : appModel!.localeCode),

appModel

class AppModel with ChangeNotifier {  IndexSetting indexSetting = IndexSetting();  String localeCode = 'en';  Future init() async {    await LocalStorage.getItem('indexSetting').then((value) {      setIndexSetting(value);    });    await LocalStorage.getItem('localeCode').then((value) {      if (value != null) {        setLocale(value);      }    });  }  setIndexSetting(data) {    if (data == null) {      indexSetting = IndexSetting();      LocalStorage.remove("indexSetting");    } else {      indexSetting = IndexSetting.fromJson(data);      LocalStorage.setItem("indexSetting", indexSetting);    }    notifyListeners(); //  }  setLocale(String code) {    localeCode = code;    LocalStorage.setItem("localeCode", code);    notifyListeners(); //  }}

子页面

Row(            mainAxisAlignment: MainAxisAlignment.spaceBetween,            children: [              Text("中文"),              Radio(                  value: 1,                  groupValue: radio,                  activeColor: ColorConst.primaryColor,                  onChanged: (value) {                    radio = 1;                    appModel?.setLocale("zh");                    setState(() {});                  }),            ],          ),          Row(            mainAxisAlignment: MainAxisAlignment.spaceBetween,            children: [              Text("English"),              Radio(                  value: 2,                  groupValue: radio,                  activeColor: ColorConst.primaryColor,                  onChanged: (value) {                    radio = 2;                    appModel?.setLocale("en");                    setState(() {});                  }),            ],          )

共有1个答案

阎昌勋
2023-09-13

问题原因是在根页面中,监听代码appModel!.addListener在子页面中触发notifyListeners的操作之前执行了。在initState中的Future.delayed(Duration.zero, () { ... })将监听代码加入了微任务队列,而子页面中的操作是同步执行的,所以在子页面触发notifyListeners之前,监听代码已经执行完毕,导致没有执行。

解决方法是将监听代码放在子页面中的onChanged回调中,保证在触发notifyListeners之后再执行监听代码。

修改后的子页面代码如下:

Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  children: [    Text("中文"),    Radio(      value: 1,      groupValue: radio,      activeColor: ColorConst.primaryColor,      onChanged: (value) {        radio = 1;        appModel?.setLocale("zh");        setState(() {});        appModel!.addListener(() {          print("change ${appModel!.localeCode}");        });      },    ),  ],),Row(  mainAxisAlignment: MainAxisAlignment.spaceBetween,  children: [    Text("English"),    Radio(      value: 2,      groupValue: radio,      activeColor: ColorConst.primaryColor,      onChanged: (value) {        radio = 2;        appModel?.setLocale("en");        setState(() {});        appModel!.addListener(() {          print("change ${appModel!.localeCode}");        });      },    ),  ],)

这样修改后,当触发notifyListeners时,监听代码就会被执行。

 类似资料:
  • 我面临QuartzScheduler触发器定义的问题。 2019年2月28日星期四16:27:30 IST:开始时间 0/20 0 0 ? * * * Cron表达式 2019年2月28日星期四16:29:30 IST结束时间 触发器schedulerAdderTrigger=触发器生成器。newTrigger()。withIdentity(触发键)。startAt(schedulerdata.g

  • 问题内容: 我正在寻找一种在页面加载时自动“单击”项目的方法。 我尝试使用 但这似乎行不通吗?但是,当我进入Firebug的控制台并运行脚本时,它可以工作。 可以在加载时使用触发事件吗? 问题答案: 您尝试触发的点击处理程序很可能也通过附加了。可能发生的情况是您在附加处理程序之前触发了事件。解决方法是使用: 10ms的延迟将导致该函数在所有处理程序被调用后立即运行。

  • 描述:切换一个新的没打开的界面。就会触发打开界面的created。 解释:当前打开A界面,从A界面进入B界面,A界面触发created。再打开C界面,A界面又触发created。 B界面和C界面已经打开过,这时候随便切换,不再触发A界面的created 解决了:router-view 多加了key导致的刷新

  • 问题内容: 我正在将angularJS与一起使用。当我运行Web应用程序时,所有链接均正常工作,并且没有500错误。 但是,当我刷新页面时,出现了500条这样的错误: 找不到部分视图“联系人”,或者没有视图引擎支持搜索到的位置。搜索了以下位置: 我正在使用angularJS控制器从./templates文件夹中加载模板,而angularJS做得很好。 有人知道为什么我会收到此错误以及如何解决该错误

  • 我很难找到sinon间谍没有被触发的原因。在下面的测试中,两个控制台语句都报告为false,因此两个方法都没有被调用(以防出现错误)。 这是我的一个摩卡测试通常的样子: }); PostOnToller中的方法: 最后是PostModel中的方法: 如果我以正常的方式调用方法,它们会执行查找,返回预期的Posts数组。但是,不会执行间谍。另外,如果我将控制器类中的方法更改为 间谍函数(res)确实

  • 问题内容: 我正在尝试编写一个触发器来填充一个包含有关雇员的最新工资信息的表。我有一个问题,我现在无法完全绕开我的头。 这是要填充的表: 这是我的触发器: 触发器编译没有问题,但是当我尝试运行此更新时,Oracle告诉我触发器无效。是什么原因造成的? 问题答案: 您已按块显示了代码。但似乎您正在运行一起显示为脚本的内容,最初没有进行更新: 在SQL Developer中作为脚本运行时,脚本输出窗口