我试图了解控制StatefulWidget状态之外的状态的最佳实践。
我定义了以下接口。
abstract class StartupView {
Stream<String> get onAppSelected;
set showActivity(bool activity);
set message(String message);
}
我想创建一个StatefulWidget StartupPage
来实现这个接口。我希望这个Widget能完成以下任务:
1.当一个按钮被按下时,它将通过onAppSelected
流发送一个事件。一个控制器将监听这个事件并执行一些操作(DB调用、服务请求等)。
1.控制器可以调用showActivity
或set message
,使视图显示进度和消息。
因为有状态Widget不将其State公开为属性,所以我不知道访问和修改State属性的最佳方法。
我希望使用它的方式如下:
Widget createStartupPage() {
var page = new StartupPage();
page.onAppSelected.listen((app) {
page.showActivity = true;
//Do some work
page.showActivity = false;
});
}
我曾考虑过通过传入我希望它在createState()
中返回的状态来示例化Widget,但感觉不对。
关于我们为什么采用这种方法的一些背景信息:我们目前有一个Dart Web应用程序。为了视图-控制器分离、可测试性和对Flutter的前瞻性思考,我们决定为应用程序中的每个视图创建一个接口。这将允许WebComponent或Flutter Widget实现此接口,并保持所有控制器逻辑不变。
7条答案
按热度按时间3mpgtkmj1#
与 其他 有 状态 小 部件 交互 的 方式 有 多种 。
第 一 个 也 是 最 直接 的 方法 是 通过
context.findAncestorStateOfType
。通常 Package 在
Stateful
子类 的 静态 方法 中 , 如下 所 示 :中 的 每 一 个
例如 ,
Navigator
就是 这样 工作 的 。亲 :
缺点 :
State
属性 或 手动 调用setState
State
子 类别当 你 想 访问 一 个 变量 时 , 不要 使用 这个 方法 , 因为 当 变量 改变 时 , 你 小 部件 可能 不会 重新 加载 。
有时 候 , 您 可能 希望 访问 一些 属性 , 而 不是 方法 。 问题 是 , 您 最 有 可能 希望 您 的 小 部件 在 该 值 随 时间 变化 时 更新 。
在 这种 情况 下 , dart 提供 了
Stream
和Sink
, flutter 在 其 之上 又 增加 了InheritedWidget
和Listenable
, 如ValueNotifier
, 它们 都 做 了 相对 相同 的 事情 :当 与StreamBuilder
/context.dependOnInheritedWidgetOfExactType
/AnimatedBuilder
耦合 时 订阅 值 改变 事件 。这 是 当 你 想 让 你 的
State
公开 一些 属性 时 的 首选 解决 方案 。 我 不会 涵盖 所有 的 可能 性 , 但 这里 有 一 个 使用InheritedWidget
的 小 例子 :首先 , 我们 有 一 个
InheritedWidget
, 它 公开 了 一 个count
:格式
然后 我们 有 示例 化 这个
InheritedWidget
的State
格式
最 后 , 我们 有
CountBody
, 它 获取 这个 公开 的count
格式
优点 :
findAncestorStateOfType
await for
或async*
)缺点 :
您 可以 从 widget 发送 一 个
Notification
, 并 让State
订阅 这些 通知 , 而 不是 直接 调用State
上 的 方法 。Notification
的 示例 如下 :格式
要 调度 通知 , 只需 在 通知 示例 上 调用
dispatch(context)
, 它 就会 冒泡 。格式
注意 : 你 需要 把 上面 的 代码 行 * * 放在 一 个 类 * * 里面 , 否则 没有 上下文 , 不能 调用 通知 。
任何 给定 的 小 部件 都 可以 使用
NotificationListener<T>
监听 其子 部件 发送 的 通知 :格式
例如
Scrollable
, 它 可以 调度ScrollNotification
, 包括 开始/结束/过度 滚动 。 然后 ,Scrollbar
使用 它 来 了解 滚动 信息 , 而 无需 访问ScrollController
优点 :
State
上 做 什么 。 它 是State
, 订阅 由 其子 项 触发 的 事件State
属性缺点 :
ttcibm8c2#
你可以用一个静态方法公开状态的小部件,一些flutter例子就是这样做的,我也开始使用它:
然后,您可以通过调用
StartupPage.of(context).doSomething();
来访问该状态。这里需要注意的是,您需要有一个BuildContext,该页面位于其树中的某个位置。
gk7wooem3#
还有另一种访问State属性/方法的常用方法:
nzk0hqpo4#
我做:
而外面只是
3mpgtkmj5#
在尝试解决类似问题时,我发现
ancestorStateOfType()
和TypeMatcher
已经被弃用。相反,必须使用findAncestorStateOfType()
。然而,根据文档,“调用此方法相对昂贵”。findAncestorStateOfType()
方法的文档可以在here中找到。在任何情况下,要使用
findAncestorStateOfType()
,可以实现以下内容(这是使用findAncestorStateOfType()
方法对正确答案的修改):状态的访问方式与正确答案中描述的相同(使用
StartupPage.of(context).yourFunction()
)。我想用新方法更新帖子。axkjgtzd6#
您可以使用eventify
此库提供了向发射器或发布器注册事件通知并在发生事件时获得通知的机制。
您可以执行以下操作:
我想不出有什么事情是事件驱动编程所不能实现的。你是无限的!
“自由不能被赐予--它必须被实现。”--埃尔伯特·哈伯德
xvw2m8pv7#
您是否考虑过将状态提升到父部件?据我所知,这是React中管理状态的一种常见方式,尽管不如Redux理想,而此repository演示了如何将此概念应用于Flutter应用。