• flutter中使用redux之多界面互动


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

    例子:登录

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

    目标:

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

    clipboard.png

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

    LoginPage.dart代码如下:

    import 'package:flutter/material.dart';
    import 'package:flutter_redux/flutter_redux.dart';
    import 'package:flutter_use_redux/reducers.dart';
    import 'package:redux/redux.dart';
    import 'dart:async';
    import 'package:flutter/cupertino.dart';
    
    
    typedef Future CallLogin(String account,String pwd);
    
    class LoginPageState extends State<LoginPage>{
    
      String _account;
      String _pwd;
    
    
    
      bool isLogin;
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text("登录"),
          ),
          body: new Form(
              onChanged: (){
                print("changed");
              },
              onWillPop: () async{
                return true;
              },
              child: new Padding(padding: new EdgeInsets.all(10.0),child: new Column(
    
                children: <Widget>[
                  new TextFormField( decoration:new InputDecoration(labelText: "请输入账号") ,
                    onSaved: (String value){
                     _account = value;
                    },  ///保持一下输入的账号
                    validator: (String value)=> value.isEmpty ? "请输入账号" : null, ),
                  new TextFormField(decoration:new InputDecoration(labelText: "请输入密码"),
                      onSaved: (String value)=>_pwd = value, ///保持一下输入的密码
                      validator: (String value)=> value.isEmpty ? "请输入密码" : null),
                  new FormField(builder: (FormFieldState s){
                    return new Center(
                      child: new RaisedButton(onPressed: () async{
    
                      FormState state = Form.of(s.context);
                      if(state.validate()){
                        //如果验证成功,那么执行登录逻辑
                        state.save();
                        print("Login success $_account" );
                        //这里交给设置好的逻辑去执行操作
                        try{
                          await widget.callLogin(_account,_pwd);
                          showDialog(context: context,builder: (c){
    
                            return new CupertinoAlertDialog(
                              title: new Text("登录成功"),
                              actions: <Widget>[
                                new Center(
                                  child: new RaisedButton(
                                    onPressed:(){
                                      Navigator.of(context).pop();
                                      Navigator.of(context).pop();
                                    },
                                    child: new Text("ok"),
                                  )
                                )
                              ],
                            );
    
                          });
                        //  Navigator.of(context).pop();
                        }catch(e){
                          showDialog(context: context,builder: (c){
    
                            return new CupertinoAlertDialog(
                              title: new Text("登录失败$e"),
                              actions: <Widget>[
                                new Center(
                                    child: new RaisedButton(
                                      onPressed:(){
                                        Navigator.of(context).pop();
                                      },
                                      child: new Text("ok"),
                                    )
                                )
                              ],
                            );
    
                          });
                          ///登录失败,提示一下用户
                          print("登录失败! $e");
                        }
    
                      }
    
                    },child: new Text("提交"),)
                    );
                  })
                ],
    
              ),)),
        );
      }
    
    }
    
    class LoginPage extends StatefulWidget{
    
      CallLogin callLogin;
    
    
      LoginPage({this.callLogin});
    
      @override
      State<StatefulWidget> createState() {
        return new LoginPageState();
      }
    
    }
    注意:这个组件其实并没有使用redux,登录逻辑使用外部传递过来的函数来处理:
     CallLogin callLogin;
      LoginPage({this.callLogin});
    
     ...
    //执行登录逻辑
         await widget.callLogin(_account,_pwd);
     ...                 
    为什么要这么做呢?好处有哪些?
    • 减少组件之间的依赖关系
    • 减少本类的职责,将本类的职责变成只展示ui
    • 本类可单独单元测试,单独工作,只要传进来一个模拟的逻辑函数
    那么在哪里将登录逻辑传递进来呢?

    ···
    routes: {

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

    ···

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

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

    附件:

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

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

  • 相关阅读:
    【进阶3-5期】深度解析 new 原理及模拟实现(转)
    ios 手机端 input 框上方有内阴影
    手机端上点击input框软键盘出现时把input框不被覆盖,显示在屏幕中间(转)
    xampp 搭建好本地服务器以后手机无法访问
    【进阶3-4期】深度解析bind原理、使用场景及模拟实现(转)
    阿里云播放器
    flex下部固定高,上部不固定,而且超过内容要滚动
    Vue项目笔记
    jQuery实现鼠标点击div外的地方div隐藏消失的效果(转)
    android WebView详细使用方法(转)
  • 原文地址:https://www.cnblogs.com/twodog/p/12136494.html
Copyright © 2020-2023  润新知