为什么 Flutter 对话框没有在更改通知程序上重建?

问题描述

嗯,这个问题有点简单,但需要以特定的方式完成。首先,我有一个扩展“ChangeNotifier”的类,该类将执行一些异步任务,因此在执行此操作时,有一个变量指示该类当前是否忙碌,到目前为止它可以完美运行。

使用 Riverpod 作为状态管理我实例化了所述类并沿着我的小部件树提供它,但是有一个小部件需要显示一个对话框,并且在这个对话框中它可以从我一直传递的类中执行异步任务。除了我想在这个对话框中显示一个 CircularProgressIndicator 之外,一切都有效,而且它似乎没有对状态变化做出正确的反应。

这是重新创建场景的示例代码

import 'package:Flutter/material.dart';
import 'package:Flutter_hooks/Flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

final dataProvider = ChangeNotifierProvider<Data>((_) => Data());

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'huh?',theme: ThemeData(primarySwatch: Colors.blue),home: FirstPage(),);
  }
}

class FirstPage extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final data = useProvider(dataProvider);
    print('DATA STATE [source: FirstPage,data: ${data.loading}]');
    return Scaffold(
      body: Center(
        child: Container(
          width: 200,height: 50,child: ElevatedButton(
            child: Text('show dialog'),onpressed: () => showDialog(
              context: context,builder: (_) => Alert(data: data),),);
  }
}

class Alert extends StatelessWidget {
  const Alert({required this.data});
  final Data data;
  Widget build(BuildContext context) {
    print('DATA STATE [source: Alert,data: ${data.loading}]');
    return AlertDialog(
      content: Container(
        width: 500,height: 500,padding: EdgeInsets.symmetric(horizontal: 100,vertical: 200),child: ElevatedButton(
          child: data.loading ? CircularProgressIndicator(color: Colors.white) : Text('click here'),onpressed: () async => await data.randomTask(),);
  }
}

class Data extends ChangeNotifier {
  Data({
    this.loading = false,});
  bool loading;

  Future<void> randomTask() async {
    print('Actually waiting 3 seconds..');
    _update(loading: true);
    await Future.delayed(Duration(seconds: 3));
    print('Waiting done.');
    _update(loading: false);
  }

  void _update({bool? loading}) {
    this.loading = loading ?? this.loading;
    notifyListeners();
  }
}

请注意我放置的打印件,因为如果您运行应用程序,您将在控制台上看到如下输出

DATA STATE [source: FirstPage,data: false]
DATA STATE [source: Alert,data: false]
Actually waiting 3 seconds..
DATA STATE [source: FirstPage,data: true]
Waiting done.
DATA STATE [source: FirstPage,data: false]

这意味着状态实际上正在发生变化,并且一切正常,除了似乎是静态的对话框。

我已经尝试添加一个“加载”布尔值作为“警报”小部件的一部分,并让它管理自己的状态,并且它可以工作,但是代码并不像我想要的那样干净,因为类“数据”应该管理这种东西。

有什么可以做的吗?

提前致谢!

解决方法

添加 StatefulBulider 即可

class Alert extends StatelessWidget {
  const Alert({required this.data});
  final Data data;
  Widget build(BuildContext context) {
    print('DATA STATE [source: Alert,data: ${data.loading}]');
    return AlertDialog(
      content: StatefulBuilder(builder: (context,setState) {
        return Container(
          width: 500,height: 500,padding: EdgeInsets.symmetric(horizontal: 100,vertical: 200),child: ElevatedButton(
            child: data.loading
                ? CircularProgressIndicator(color: Colors.white)
                : Text('click here'),onPressed: () async => await data.randomTask(),),);
      }),);
  }
}