上一篇文章,我们介绍了如何在flutter中使用redux。在上一篇文章的例子中,我们使用了单界面集成redux,但是在实际项目中,我们通常涉及多个模块,每个模块涉及多个界面,那么如何使用redux整合模块,并实现模块和界面间的消息传递呢?

例子:登录

接着上篇文章,这次的例子稍微复杂一点:

目标:

  • 实现登录界面,实现基本登录逻辑
  • 成功之后将结果通知到其他界面

先将AppState等状态有关的移动到reducers.dart,创建LoginPage.dart

LoginPage.dart代码如下:

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_redux/flutter_redux.dart';
  3. import 'package:flutter_use_redux/reducers.dart';
  4. import 'package:redux/redux.dart';
  5. import 'dart:async';
  6. import 'package:flutter/cupertino.dart';
  7. typedef Future CallLogin(String account,String pwd);
  8. class LoginPageState extends State<LoginPage>{
  9. String _account;
  10. String _pwd;
  11. bool isLogin;
  12. @override
  13. void initState() {
  14. super.initState();
  15. }
  16. @override
  17. void dispose() {
  18. super.dispose();
  19. }
  20. @override
  21. Widget build(BuildContext context) {
  22. return new Scaffold(
  23. appBar: new AppBar(
  24. title: new Text("登录"),
  25. ),
  26. body: new Form(
  27. onChanged: (){
  28. print("changed");
  29. },
  30. onWillPop: () async{
  31. return true;
  32. },
  33. child: new Padding(padding: new EdgeInsets.all(10.0),child: new Column(
  34. children: <Widget>[
  35. new TextFormField( decoration:new InputDecoration(labelText: "请输入账号") ,
  36. onSaved: (String value){
  37. _account = value;
  38. }, ///保持一下输入的账号
  39. validator: (String value)=> value.isEmpty ? "请输入账号" : null, ),
  40. new TextFormField(decoration:new InputDecoration(labelText: "请输入密码"),
  41. onSaved: (String value)=>_pwd = value, ///保持一下输入的密码
  42. validator: (String value)=> value.isEmpty ? "请输入密码" : null),
  43. new FormField(builder: (FormFieldState s){
  44. return new Center(
  45. child: new RaisedButton(onPressed: () async{
  46. FormState state = Form.of(s.context);
  47. if(state.validate()){
  48. //如果验证成功,那么执行登录逻辑
  49. state.save();
  50. print("Login success $_account" );
  51. //这里交给设置好的逻辑去执行操作
  52. try{
  53. await widget.callLogin(_account,_pwd);
  54. showDialog(context: context,builder: (c){
  55. return new CupertinoAlertDialog(
  56. title: new Text("登录成功"),
  57. actions: <Widget>[
  58. new Center(
  59. child: new RaisedButton(
  60. onPressed:(){
  61. Navigator.of(context).pop();
  62. Navigator.of(context).pop();
  63. },
  64. child: new Text("ok"),
  65. )
  66. )
  67. ],
  68. );
  69. });
  70. // Navigator.of(context).pop();
  71. }catch(e){
  72. showDialog(context: context,builder: (c){
  73. return new CupertinoAlertDialog(
  74. title: new Text("登录失败$e"),
  75. actions: <Widget>[
  76. new Center(
  77. child: new RaisedButton(
  78. onPressed:(){
  79. Navigator.of(context).pop();
  80. },
  81. child: new Text("ok"),
  82. )
  83. )
  84. ],
  85. );
  86. });
  87. ///登录失败,提示一下用户
  88. print("登录失败! $e");
  89. }
  90. }
  91. },child: new Text("提交"),)
  92. );
  93. })
  94. ],
  95. ),)),
  96. );
  97. }
  98. }
  99. class LoginPage extends StatefulWidget{
  100. CallLogin callLogin;
  101. LoginPage({this.callLogin});
  102. @override
  103. State<StatefulWidget> createState() {
  104. return new LoginPageState();
  105. }
  106. }

注意:这个组件其实并没有使用redux,登录逻辑使用外部传递过来的函数来处理:

  1. CallLogin callLogin;
  2. LoginPage({this.callLogin});
  3. ...
  4. //执行登录逻辑
  5. await widget.callLogin(_account,_pwd);
  6. ...

为什么要这么做呢?好处有哪些?

  • 减少组件之间的依赖关系
  • 减少本类的职责,将本类的职责变成只展示ui
  • 本类可单独单元测试,单独工作,只要传进来一个模拟的逻辑函数

那么在哪里将登录逻辑传递进来呢?

···
routes: {

  1. "login":(BuildContext context)=>new StoreConnector(builder: ( BuildContext context,Store<AppState> store ){
  2. return new LoginPage(callLogin: (String account,String pwd) async{
  3. print("正在登录,账号$account,密码:$pwd");
  4. // 为了模拟实际登录,这里等待一秒
  5. await new Async.Future.delayed(new Duration(milliseconds: 1000));
  6. if(pwd != "123456"){
  7. throw ("登录失败,密码必须是123456");
  8. }
  9. print("登录成功!");
  10. store.dispatch(new LoginSuccessAction(account: account));
  11. },);
  12. }, converter: (Store<AppState> store){
  13. return store;
  14. }),

···

在导入这个登录组件到应用程序路由上面的时候,这个时候将逻辑和Store进行对接,这样做,就将逻辑和ui彻底的分开了。

这里涉及到异步操作,那么就会遇到所谓“副作用”问题。
随着项目的增大,reducer也会越来越大,那么有什么办法可以管理呢?
这些问题我们改天再分享。

附件:

老规矩,代码在这里:
https://github.com/jzoom/flut...

如有疑问,请加qq群854192563讨论

flutter中使用redux之多界面互动的更多相关文章

  1. 理解 Flutter 中的 Key

    概览 在 Flutter 中,大概大家都知道如何更新界面视图: 通过修改 Stata 去触发 Widget 重建,触发和更新的操作是 Flutter 框架做的. 但是有时即使修改了 State,Flu ...

  2. 在React中使用Redux

    这是Webpack+React系列配置过程记录的第六篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  3. 在Flutter中嵌入Native组件的正确姿势是...

    引言 在漫长的从Native向Flutter过渡的混合工程时期,要想平滑地过渡,在Flutter中使用Native中较为完善的控件会是一个很好的选择.本文希望向大家介绍AndroidView的使用方式 ...

  4. mvp 在 flutter 中的应用

    在 Android 应用程序开发过程中,我们经常会用到一些所谓的架构方法,如:mvp,mvvm,clean等.之所以这些方法会被推崇是因为他们可以大大的解耦我们的代码的功能模块,让我们的代码在项目中后 ...

  5. Flutter 中文文档网站 flutter.cn 正式发布!

    在通常的对 Flutter 介绍中,最耳熟能详的是下面四个特点: 精美 (Beautiful):充分的赋予和发挥设计师的创造力和想象力,让你真正掌控屏幕上的每一个像素. ** 极速 (Fast)**: ...

  6. Flutter中管理路由栈的方法和应用

    原文地址:https://www.jianshu.com/p/5df089d360e4 本文首先讲的Flutter中的路由,然后主要讲下Flutter中栈管理的几种方法. 了解下Route和Navig ...

  7. 在Flutter中构建布局

    这是在Flutter中构建布局的指南.首先,您将构建以下屏幕截图的布局.然后回过头, 本指南将解释Flutter的布局方法,并说明如何在屏幕上放置一个widget.在讨论如何水平和垂直放置widget ...

  8. flutter中的生命周期函数

    前言:生命周期是一个组件加载到卸载的整个周期,熟悉生命周期可以让我们在合适的时机做该做的事情,flutter中的State生命周期和android以及React Native的生命周期类似. 先看一张 ...

  9. flutter 中的AppBar

    在flutter中的很多页面中,都会有下面这段代码: 对应就是下图中的红色线框区域,被称作AppBar顶部导航. 项目准备 在使用AppBar之前,我们先新建一个tabBar的项目: 然后在pages ...

随机推荐

  1. andlua,andlua发送http请求,并解析json数据

    andlua发送http请求,并解析json实例 import'cjson'import 'http'--导入cjson库url = 'https://www.baidu,com'--设置urlHtt ...

  2. 打造一款 刷Java 知识的小程序(二)

    学习Java的神器已上线,面向广大Java爱好者! 之前写的一篇:打造一款 刷Java 知识的小程序(一) 一.第二版做了什么? 第一版小程序只具有初级展示功能,知识点都是hardcode在代码里面的 ...

  3. javascript 入门 之 bootstrap 第一个程序

    <table data-toggle="table"> <thead> <tr> <th>Item ID</th> &l ...

  4. 《闲扯Redis四》List数据类型底层编码转换

    一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...

  5. C语言实现顺序表(顺序存储结构)

    顺序表(顺序存储结构)及初始化过程详解 顺序表,全名顺序存储结构,是线性表的一种.通过<线性表>一节的学习我们知道,线性表用于存储逻辑关系为"一对一"的数据,顺序表自然 ...

  6. 使用基于vuecli创建的目录推送到指定远程分支

    笔者使用vuecli创建项目目录以后,在想将该目录提交到远程仓库时发现行不通,在忙活了一下午以后写下此文 1.github上新建一空分支,然后克隆该分支地址:  https://github.com/ ...

  7. 数据结构和算法(Golang实现)(5)简单入门Golang-接口

    接口 在Golang世界中,有一种叫interface的东西,很是神奇. 一.数据类型 interface{} 如果你事前并不知道变量是哪种数据类型,不知道它是整数还是字符串,但是你还是想要使用它. ...

  8. 【Tool】使用IDEA创建简单的Java项目

    IDEA创建简单的Java项目 打开IDEA进入首页面,点击 Create New Project 点选第一项就是了,SDK就是我们的JDK,,这里我已经装好了JDK和JDK的环境变量 IDEA就能自 ...

  9. ValidForm.js的使用注意点

    dataType的值不能为"", 否则会导致错误发生:Uncaught TypeError: Cannot read property '0' of null,http请求可以发送 ...

  10. Java - window下环境配置

    JDK下载 官网:https://www.oracle.com/java/technologies/javase-jdk8-downloads.html 百度网盘: 链接:https://pan.ba ...