【问题标题】:Flutter Provider: How do I listen to a change of a class field inside a class field?Flutter Provider:如何监听类字段内部的类字段变化?
【发布时间】:2020-08-13 23:51:35
【问题描述】:

给定以下 Dart/Flutter 类结构:

import 'package:flutter/material.dart';

class A with ChangeNotifier {
  B _element1;
  B _element2;

  B get element1 => _element1;
  B get element2 => _element2;

  set element1(B value) {
    _element1 = value;
    notifyListeners();
  }

  set element2(B value) {
    _element2 = value;
    notifyListeners();
  }
}

class B {
  String x;
  String y;
}

我正在尝试收听A.element1.x 的变化,但问题是,B 类的setter 无法调用A 类的notifyListeners(),所以要么我在听A 并且不会注意到改变,或者我正在听 B,而我正在将上下文丢失给 A。

我在我的 Flutter 项目中使用 Provider 包。但我不确定,如果我误解了 Provider 包或 ChangeListeners 的概念。无论哪种方式,我都无法找到一个优雅的解决方案。

是否有可能从 A 类覆盖 B 类的 setter? 我显然可以为每个 element1 和 element2 字段(x,y)实现一个函数。但我猜这不是好的代码风格。

【问题讨论】:

  • 有多种(一如既往;))方法可以解决这个问题:您可以在 B 类中注册一个回调,然后调用 A 类的函数,以便 A 类知道何时通知侦听器因为 B 的变化。或者使用流,由 B 公开并由 A 收听。但也许最好是查看 ProxyProvider 包。我没有这方面的经验,但我认为它可能适合您的用例。这是一个article
  • 你能帮我解决一下回调函数吗?我不熟悉回调函数。我查看了这篇文章,但找不到针对我的特定问题的解决方案。我还查看了文档,但不知道如何使用 ProxyProvider 来解决我的问题。
  • 在下面发布了一个示例。这就是回调在 A 中调用 notifyListeners 的方式。我不确定这是否比仅在 A 上调用方法更好,然后在 B 上设置属性并直接调用 notifyListeners

标签: flutter dart provider flutter-change-notifier


【解决方案1】:

这是一个关于如何使用回调函数的示例。如果没有回调,A 将不会调用 notifyListeners 并且您的 Home 小部件不会重建。这是一个关于VoidCallback 是什么的简短视频:https://www.youtube.com/watch?v=fWlPwj1Pp7U

主函数和一个简单的Home 视图:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'a.dart';

void main() {
  runApp(
    ChangeNotifierProvider<A>(
      create: (context) => A(),
      child: MaterialApp(
        home: Home(),
      ),
    )
  );
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<A>(
      builder: (context, model, child) {
        return Scaffold(
          body: Container(
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('${model.element1.x}'),
                  RaisedButton(
                    child: Text("Set x of element1."),
                    onPressed: () {
                      Provider.of<A>(context, listen: false).element1.setX = 'Set to new value';
                    },
                  ),
                ],
              ),
            ),
          )
        );
      },
    );
  }
}

然后是A类:

import 'package:flutter/material.dart';
import 'package:tryout/b.dart';

class A extends ChangeNotifier {
  B _element1 = B();
  B _element2 = B();

  B get element1 => _element1;
  B get element2 => _element2;

  A() {
    _element1.callback = () => notifyListeners();
    _element2.callback = () => notifyListeners();
  }

  set element1(B value) {
    _element1 = value;
    _element1.callback = () => notifyListeners();
    notifyListeners();
  }

  set element2(B value) {
    _element2 = value;
    _element2.callback = () => notifyListeners();
    notifyListeners();
  }
}

B 类:

import 'package:flutter/cupertino.dart';

class B {
  String x = "";
  String y = "";
  VoidCallback callback;

  B({
    this.callback
  });

  set setX(String newValueX) {
    x = newValueX;
    if(callback != null) callback();
  }

  void setY(String newValueY) {
    y = newValueY;
    if(callback != null) callback();
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多