如何解决Flutter:将有状态的小部件组合成 Flutter-redux 应用程序架构
按照 this 问题,我理解为什么 StatefulWidgets 在 基于 Redux 的 Flutter 应用 的上下文中确实有意义。这也是我正在努力实现的目标-
一个页面,它从应用程序范围的状态(登录的用户详细信息、api 数据等)“馈送”信息,还可以从它连接的 viewmodel 分派动作,但一个还包含范围较小的有状态小部件的页面,短暂的状态。诸如动画、在提交前即时验证用户输入以及根据用户操作更改 UI。
所以我对方法很感兴趣,希望这里有人可以帮助我。 目前我所有的“页面”都是通过商店连接到应用程序状态的无状态小部件,方式如下:
class LoginPage extends StatelessWidget {
final String TAG = "LoginPage";
bool isGreen = false;
LoginPage({Key key}) : super(key: key);
void changeColor() {
isGreen = !!isGreen;
}
@override
Widget build(BuildContext context) {
/// [StoreConnector] is used to convert store data (using the fromStore)
/// into a viewmodel suitable for the page.
return StoreConnector<AppState,LoginPageviewmodel>(
builder: (context,viewmodel) {
return Scaffold(
body: Column(
children: <Widget>[
Container(...),Text(
text: viewmodel.some_value_from_the_store,color: isGreen ? Colors.green : Colors.red,),ElevatedButton(
onpressed: () => changeColor(),child: Text('Press to change color'),)
],));
},converter: LoginPageviewmodel.fromStore);
}
}
在这里,我只是想根据用户点击简单地更改“LoginPage”小部件内的文本颜色,同时仍保持与商店的连接,以便 UI 在新应用程序状态信息到达时不断更新。
有没有类似我们那里的参考资料?任何人都可以提供一个例子,或者只是如何实现这一目标的基本指南? 看起来很简单,但我正在努力。
解决方法
这里有一些想法可能会有所帮助。
您的小部件需要有状态。您正在尝试跟踪随时间变化的颜色。无状态小部件仅允许最终属性 - 即您只能在创建时启动它们的值。
您的变量 isGreen 和方法 changeColor() 应该是状态对象的一部分。你的 build() 方法也会去那里。
下一步 - 当你调用你的方法时,你应该调用:
void changeColor() {
setState(() {isGreen = !isGreen;});
}
我认为在您的代码中您没有翻转值(=!!iGreen 与 =isGreen 相同)。但更重要的是 - 您没有告诉框架应该重建您的小部件。 您可以自行测试:单击一次(在您更正“!!”之后)。什么都不会发生。如果您在模拟器中强制刷新 - 您应该看到颜色确实发生了变化。这是因为您手动刷新了它。 setState() 为您完成:它将运行您提供的代码,然后调用 Flutter 告诉它刷新您的小部件。请参阅 - flutter 没有魔术触发器,并且不会观察您的代码来决定何时刷新您的小部件。 setState() 告诉它这样做。
作为一般规则:您的应用程序状态 - 即与多个小部件(或页面)共享的数据应该“提升”小部件树,并保存在 Provider 类中。
有状态的小部件应该只保留与它们直接相关的数据,并且只保留与它们直接相关的数据。通常,这是帮助呈现提供程序数据的数据。例如: -Provider 将保留您显示的项目列表。您的有状态小部件将跟踪当前选定的项目 -Provider 保留要显示的文本。您的 Stateful 小部件保持字体大小、字体颜色等,允许用户在特定小部件上更改它,但不能在使用相同数据的所有小部件上进行更改。
在您的示例中 - 您的云在屏幕上有多个登录小部件(出于某种原因)。在这种情况下: - 如果您希望所有登录小部件都改变颜色 - 将 isGreen 保留在您的提供者类中。在这种情况下,您的小部件可以是无状态的。 - 如果你只想要你点击的小部件来改变颜色 - 这属于你的有状态小部件,因为没有人关心这个值。
让我用应该做你想做的代码来更新这个。将小部件连接到商店的方式与有状态和无状态小部件的工作方式相同。
注意 - 我注释掉了您连接到商店的代码,只是为了显示您的小部件将如何改变颜色。取消对商店代码的注释,您应该很高兴。
您可以在 https://dartpad.dev/ 中快速运行,只需复制/粘贴代码。
// Copyright (c) 2019,the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',debugShowCheckedModeBanner: false,theme: ThemeData(
primarySwatch: Colors.blue,),home: LoginPage(),);
}
}
class LoginPage extends StatefulWidget {
final String TAG = "LoginPage";
LoginPage({Key key}) : super(key: key);
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool isGreen = false;
void changeColor() {
setState(() {
isGreen = !isGreen;
});
}
@override
Widget build(BuildContext context) {
/// [StoreConnector] is used to convert store data (using the fromStore)
/// into a ViewModel suitable for the page.
//return StoreConnector<AppState,LoginPageViewModel>(
//builder: (context,viewModel) {
return Scaffold(
body: Column(
children: <Widget>[
Container(),Text(
'viewModel.some_value_from_the_store',style: TextStyle(color: isGreen ? Colors.green : Colors.red),ElevatedButton(
onPressed: () => changeColor(),child: Text('Press to change color'),)
],));
//},//converter: LoginPageViewModel.fromStore);
//}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。