手把手入门Fish-Redux开发flutter(中)

手把手入门Fish-Redux开发flutter(上)
手把手入门Fish-Redux开发flutter(中)
手把手入门Fish-Redux开发flutter(下)

上一次我们创建了项目,集成了 fish-redux ,安装了插件,并写出第一个页面,这次我们更详细的了解 fish-redux 。并实现一个简单的列表。效果:


image

1 跳转到一个新的页面

1.1 创建一个新页面

我们用上一篇讲述的的方式:创建 package 、创建 FishReduxTemplate 来得到新的页面,取名叫 Grid 。


image

把这个页面也添加到app.dart的页面路由中。app.dart修改如下


Widget createApp() {
  final AbstractRoutes routes = PageRoutes(
    pages: <String, Page<Object, dynamic>>{
      'entrance_page': EntrancePage(),
      'grid_page': GridPage(),  //添加这一行
    },
  );

  //省略 ...
}

然后编辑这个页面的 view.dart,暂且让它显示一行文字。/grid/view.dart如下

import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';
import 'state.dart';

Widget buildView(GridState state, Dispatch dispatch, ViewService viewService) {
  return Scaffold(
    appBar: new AppBar(
      title: new Text('Grid页面'),
    ),
    body: Text("Grid页面"),
  );
}

1.2 完成页面的跳转

理清思路:为了从 entrance 页面跳转到 grid 页面。我们需要:

  1. 为 entrance 页面定义跳转的 action
  2. 在 entrance 页面跳转的地方 dispatch 这个 action
  3. effect 处理这个 action,即进行页面跳转(这里不涉及到状态的更新,所以不在 reducer 里处理啦)

第一步 定义 action

我们打开 /entrance/action.dart 发现由模板创建的代码中为我们默认定义了一个action,我们照它的样子添加自己的 action ,取名叫 openGrid 表示打开 grid 页面的事件。修改后的 /entrance/action.dart 如下

import 'package:fish_redux/fish_redux.dart';

enum EntranceAction { action, openGrid }//增加openGrid

class EntranceActionCreator {
  static Action onAction() {
    return const Action(EntranceAction.action);
  }
  //我们定义的
  static Action onOpenGrid() {
    return const Action(EntranceAction.openGrid);
  }
}

第二步 发送Action

我们打开 /entrance/view.dart,为 RaisedButton 写点击事件 onPress。在这里dispatch我们定义的OpenGrid事件。

            dispatch(EntranceActionCreator.onOpenGrid());

修改后的 /entrance/view.dart如下

image

第三步 接收并处理事件

打开 /entrance/effect.dart,让它接收并处理我们定义的 OpenGrid Action。 /entrance/effect.dart代码如下

import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/widgets.dart' hide Action;  //注意1
import 'action.dart';
import 'state.dart';

Effect<EntranceState> buildEffect() {
  return combineEffects(<Object, Effect<EntranceState>>{
    EntranceAction.action: _onAction,
    EntranceAction.openGrid: _onOpenGrid,   //接收openGrid事件 
  });
}

void _onAction(Action action, Context<EntranceState> ctx) {
}

//处理openGrid事件
void _onOpenGrid(Action action, Context<EntranceState> ctx) {
  Navigator.of(ctx.context).pushNamed('grid_page', arguments: null);    //注意2
}

这里有两个地方要注意。第一个地方是由于我们跳转页面引入的 widgets.dart 包含 Action 类,会与 fish-redux 的 Action 冲突并报错,所以在 import 时需要 hide Action ,之后就不在赘述。另外,pushNamed() 方法第一个参数就是我们在 app.dart 里面定义的页面路由。

然后我们运行看看效果:点击进入,跳转到了grid页面。


image

2 简单的列表

现在我们来把 grid 页面改造成一个简单的列表。

2.1 定义数据格式

我新建一个 model.dart 存放我的数据实体类 。我在 GridModel 简单的定义了一个 name 字段 model.dart 如下

image

然后在 grid 页面的 state.dart 中,创建数据的集合。修改后端 /grid/state.dart如下

import 'package:fish_redux/fish_redux.dart';
import '../model.dart';

class GridState implements Cloneable<GridState> {
  
  List<GridModel> models;   // 存放数据

  @override
  GridState clone() {
    return GridState()
    ..models = models;      //clone规则
  }
}

GridState initState(Map<String, dynamic> args) {
  return GridState();
}

2.2 在界面上展示

接着我们在页面中通过 gridview 展示我们的数据,列表的数据就采用 state 中的 models。修改 /grid/view.dart 如下

import 'package:fish_redux/fish_redux.dart';
import 'package:flutter/material.dart';

import 'state.dart';

Widget buildView(GridState state, Dispatch dispatch, ViewService viewService) {
  return Scaffold(
    appBar: new AppBar(
      title: new Text('Grid页面'),
    ),
    body: new GridView.count(
      crossAxisCount: 2,//列数
      crossAxisSpacing: 20.0,// 左右间隔
      mainAxisSpacing: 20.0,// 上下间隔
      childAspectRatio: 1 / 1, //宽高比
      padding: EdgeInsets.all(20),
      children: new List.generate(state.models.length, (index) {//使用state里面的models生成列表
        return Center(
          child: Card(
            color: Colors.lightBlueAccent,
            child: InkWell(
              splashColor: Colors.blue.withAlpha(100),
              onTap: () {
                //todo 点击事件
              },
              child: Container(
                width: 200,
                height: 200,
                child: Center(
                  child: Text(state.models[index].name),//展示name字段
                ),
              ),
            ),
          ));
      }),
    ),
  );
}

数据格式和展示样式都已经完成,接下来我们来获得数据。

2.3 数据来源

我创建一个 api.dart 用来进行数据请求。

image

我创建一个单例 Api ,把它作为全局的数据来源。然后完成一个获得 GridModel 数据的函数来给我们 grid 页面提供数据。 api.dart 如下

import 'model.dart';

class Api {
  factory Api() {
    return _get();
  }

  static Api _instance;

  Api._internal() {
    //init Api instance
  }

  static _get() {
    if (_instance == null) {
      _instance = Api._internal();
    }
    return _instance;
  }

  
  List<GridModel> getGridData() {
    return [
      GridModel(name: "第一块"),
      GridModel(name: "第二块"),
      GridModel(name: "第三块"),
      GridModel(name: "第四块"),
      GridModel(name: "第五块"),
      GridModel(name: "第六块"),
      GridModel(name: "第七块"),
      GridModel(name: "第八块"),
      GridModel(name: "第九块"),
      GridModel(name: "第十块"),
    ];
  }
}

2.4 加载数据

我们需要在 grid 页面进入时进行数据加载。首先通过 effect 接收 state 初始化的生命周期事件,在 state 初始化的时候,我们 dispatch 一个加载数据的 action 给 reducer,reducer 接收事件,请求数据并更新 state 。

第一步 定义action

/grid/action.dart 中添加一个 action, 取名 loadData。添加后如下

import 'package:fish_redux/fish_redux.dart';

enum GridAction { action, loadData }

class GridActionCreator {
  static Action onAction() {
    return const Action(GridAction.action);
  }
  
  static Action onLoadData() {
    return Action(GridAction.loadData);
  }
}

第二步 初始化时发送action

然后在 effect 中监听初始化事件,并发送 loadData Action。修改后的 /grid/effect.dart 如下

import 'package:fish_redux/fish_redux.dart';
import 'action.dart';
import 'state.dart';

Effect<GridState> buildEffect() {
  return combineEffects(<Object, Effect<GridState>>{
    Lifecycle.initState: _init, //页面初始化
    GridAction.action: _onAction,
  });
}

void _onAction(Action action, Context<GridState> ctx) {
}

void _init(Action action, Context<GridState> ctx) {
  ctx.dispatch(GridActionCreator.onLoadData()); //发送事件
}

第三步 接收action并更新state

最后在 reducer 中接收 loadData 事件,调用 Api 请求数据, 并更新 state 。修改后的 /grid/reducer.dart如下

import 'package:fish_redux/fish_redux.dart';
import '../api.dart';
import 'action.dart';
import 'state.dart';

Reducer<GridState> buildReducer() {
  return asReducer(
    <Object, Reducer<GridState>>{
      GridAction.action: _onAction,
      GridAction.loadData: _onLoadData, //接收loadData Action
    },
  );
}

GridState _onAction(GridState state, Action action) {
  final GridState newState = state.clone();
  return newState;
}

//初始化数据
GridState _onLoadData(GridState state, Action action) {
  final GridState newState = state.clone()..models = Api().getGridData();//从Api请求数据
  return newState;
}

运行一下看看效果


image

🤗如果我的内容对您有帮助,欢迎点赞、评论、转发、收藏。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335