在上一篇文章,咱們介紹瞭如何在flutter中使用redux。在上一篇文章的例子中,咱們使用了單界面集成redux,可是在實際項目中,咱們一般涉及多個模塊,每一個模塊涉及多個界面,那麼如何使用redux整合模塊,並實現模塊和界面間的消息傳遞呢?git
接着上篇文章,此次的例子稍微複雜一點:github
目標:redux
先將AppState等狀態有關的移動到reducers.dart,建立LoginPage.dartsegmentfault
LoginPage.dart代碼以下:app
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); ...
爲何要這麼作呢?好處有哪些?
那麼在哪裏將登陸邏輯傳遞進來呢?
···
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; }),
···async
在導入這個登陸組件到應用程序路由上面的時候,這個時候將邏輯和Store進行對接,這樣作,就將邏輯和ui完全的分開了。ide
這裏涉及到異步操做,那麼就會遇到所謂「反作用」問題。
隨着項目的增大,reducer也會愈來愈大,那麼有什麼辦法能夠管理呢?
這些問題咱們改天再分享。函數
老規矩,代碼在這裏:
https://github.com/jzoom/flut...單元測試
若有疑問,請加qq羣854192563討論