simple-android-flux,深入浅出Flux
前言
Flux:
* 非形式化框架,更多的是一个思想。
* 它是典型MVC/MVP框架的一个补充。
* 学会使用Flux,需要将思路从命令式编程转向声明式编程。
* 学会使用Flux,需要明确流的概念。
复制代码
简介
Flux是Facebook用户建立客户端Web应用的前端架构,它通过利用一个单向的数据流补充了React的组合视图组件,这更是一种模式
而非正式框架,你能够无需许多新代码情况下立即开始使用Flux。
Flux应用有三个主要部分:Dispatcher调度 、存储Store和视图View(React 组件),这些不应该和
MVC:Model-View-Controll(模型-视图-控制器)混淆,控制器在Flux应用中是存在的,但是他们是controller-view(控制器-视图),
视图通常在一个结构顶部,而这种结构是用来从存储stroe获得数据,然后将数据传递到自己的子结构们,此外,Action创建者
-Dispatcher的帮助类的方法-用于支持一个语义API,这个API是描述应用程序中所有变化的可能,通常可将它们看成是Flux
更新循环的第四部分。
Flux是以单向数据流方式支持MVC,当一个用户和React视图交互时,视图会将这个动作传播到一个中央Dispatcher,一直到各种存储,
在那里保存着应用的数据和业务逻辑,这个使用React的声明式风格的过程是非常棒的,能够允许存储发送更新信息,而无需指定在状态
之间如何切换视图。(传统方式更新状态后,会推出一个新的视图页面。)
复制代码
流程图
介绍一下流程图中的各个成员:
复制代码
- Dispatcher:整个流程中唯一枢纽,负责发送和分发事件流,以及管理各个Store之间的关系。
- Store:仓库,对应MVP中的P,负责获取M并根据业务逻辑,重组M的源数据,并通知V进行视图的渲染。
- View(其实应该叫做Control-View):对应MVP中的V,对应Android中的Activity和Fragment。负责夹在xml,实现控件事件的触发,最重要的是负责接收Store中的业务数据,进行试图渲染。
- Action:一个事件,往往有明确含义,大部分场景下,其内容等同于Model。
- ActionCreator:产生Action的模块,其意义就是将原MVP中,V层控件触发的业务逻辑封装起来。
- Event:子事件,往往有明确含义,用于Store与Control-View间的通信。
有两种形式的Event:1.推Push:携带经由Store转换过后的新数据,交由Control-View,进行视图渲染;
2.拉Pull:仅发送空事件,Control-View接收后,主动去Store中获取。
复制代码
具体实例流程图展示:
以服务器交互举例,事件流的具体过程:
1.从服务器异步获取数据(也可以是一些数据库操作,本地文件读取等);
2.通过ActionCreator产生某个有明确意义的Action;
3.将该Action发送至事件总线的分发器;
4.分发器将Action发送至声明接收该Action的Store;
5.Store拆解收到Action后,直接发送Event或在接收若干个Action,集合所有事件后触发发送某个Event;
6.将该Event发送至事件总线的分发器;
7.分发器将Event发送至生接收该Action的ControlView;
8.ControlView所渲染的页面上,触发一个用户行为,通知ActionCreator。
复制代码
Android中的Flux实例演示
这个例子实现的功能是一个简易的参加唱歌比赛的歌手信息录入系统。
复制代码
Dispatcher: 负责事件的分发
private final Bus bus;
private static Dispatcher instance;public static Dispatcher get(Bus bus) {if (instance == null) {instance = new Dispatcher(bus);}return instance;
}Dispatcher(Bus bus) {this.bus = bus;
}public void register(final Object cls) {bus.register(cls);
}public void unregister(final Object cls) {bus.unregister(cls);
}public void emitChange(Store.StoreChangeEvent o) {post(o);
}public void dispatch(String type, Object... data) {if (isEmpty(type)) {throw new IllegalArgumentException("Type must not be empty");}if (data.length % 2 != 0) {throw new IllegalArgumentException("Data must be a valid list of key,value pairs");}Action.Builder actionBuilder = Action.type(type);int i = 0;while (i < data.length) {String key = (String) data[i++];Object value = data[i++];actionBuilder.bundle(key, value);}post(actionBuilder.build());
}private boolean isEmpty(String type) {return type == null || type.isEmpty();
}private void post(final Object event) {bus.post(event);
}
复制代码
SingerStore:负责数据存储以及数据更新后发送更新事件
private static SingerStore instance;
private final List<Singer> singers;public SingerStore(Dispatcher dispatcher) {super(dispatcher);singers = new ArrayList<>();
}public static SingerStore get(Dispatcher dispatcher) {if (instance == null) {instance = new SingerStore(dispatcher);}return instance;
}public List<Singer> getSingers() {return singers;
}@Override
@Subscribe
public void onAction(Action action) {switch (action.getType()) {case SingerActions.ActionType.CREATE_ACTION:Singer singer =((Singer) action.getData().get(SingerActions.EventObjectKey.KEY_SINGER));addElement(singer);emitStoreChange();break;case SingerActions.ActionType.DELETE_ACTION:long id = ((long) action.getData().get(SingerActions.EventObjectKey.KEY_SINGER_ID));deleteElement(id);emitStoreChange();break;}
}private void addElement(Singer clone) {singers.add(clone);Collections.sort(singers);
}private void deleteElement(long id) {Iterator<Singer> iterator = singers.iterator();while (iterator.hasNext()) {Singer singer = iterator.next();if (singer.getId() == id) {iterator.remove();break;}}
}@Override
StoreChangeEvent changeEvent() {return new SingerStoreChangeEvent();
}public class SingerStoreChangeEvent implements StoreChangeEvent {
}
复制代码
ActionsCreator:负责产生各类事件
private static ActionsCreator instance;
final Dispatcher dispatcher;ActionsCreator(Dispatcher dispatcher) {this.dispatcher = dispatcher;
}public static ActionsCreator get(Dispatcher dispatcher) {if (instance == null) {instance = new ActionsCreator(dispatcher);}return instance;
}public void create(Singer singer) {dispatcher.dispatch(SingerActions.ActionType.CREATE_ACTION,SingerActions.EventObjectKey.KEY_SINGER,singer);
}public void delete(long id) {dispatcher.dispatch(SingerActions.ActionType.DELETE_ACTION,SingerActions.EventObjectKey.KEY_SINGER_ID,id);
}
复制代码
总结
1.Flux与其说是框架,不如说是一种思路。
2.继承MVP框架模式,将M与V隔离。额外的,其通过声明式编程,将P与V进一步解耦。
3.由于是单向的,不存在逆向调用,使整体代码流程清晰。
4.一般通过事件总线来实现。
复制代码
参考文章
其他介绍文章
附:源码地址
simple-android-flux,深入浅出Flux相关推荐
- Android进阶——深入浅出Handler(一)
Android进阶--深入浅出Handler(一) 在学习Handler之前,首先要学习一些基本概念,这将对之后的学习有所帮助. 主线程:Main Thread,又叫UI线程(UI Thread).A ...
- java me xizai_GitHub - seven332/XiaZai: A simple Android download library
XiaZai 这是一个 Android 平台上基于 OkHttp 的简单下载库. It's a simple Android download library based on OkHttp. Usa ...
- Android进程间通信 深入浅出AIDL
文中示例代码均可在demo中找到 1. AIDL概念 Android 接口定义语言 (AIDL) 与您可能使用过的其他接口语言 (IDL) 类似.您可以利用它定义客户端与服务均认可的编程接口,以便二者 ...
- Android进程间通信 深入浅出AIDL(一)
文中示例代码均可在demo中找到 1. AIDL概念 Android 接口定义语言 (AIDL) 与您可能使用过的其他接口语言 (IDL) 类似.您可以利用它定义客户端与服务均认可的编程接口,以便二者 ...
- Flux Architecture on Android
英文原文:http://lgvalle.xyz/2015/08/04/flux-architecture/ 要为安卓应用找到一个好的架构不是一件容易的事情.谷歌似乎不太在乎这个事情,因此在设计模式上, ...
- Flux架构小白入门笔记
Flux架构小白入门笔记 Flux是facebook提出的一种处理前端数据的架构,学习Flux就是学习它的思想. 这个笔记是我在学习了阮一峰老师的Flux 架构入门教程之后得出, 里面的例子和部分原文 ...
- 响应式web(三):服务当中的三种耦合,流式计算,RXJava2,Flux,Mono
响应式 Web 第三节 服务调用中的三种耦合 响应式流规范与接口 响应式流中的流量控制 Web中的响应式与请求/响应式的区别 流式处理中的Source/Sink模型 RXJava2 观察者模式同步与异 ...
- 【转】浅谈React、Flux 与 Redux
本文转自<浅谈React.Flux 与 Redux>,转载请注明出处. React React 是一个 View 层的框架,用来渲染视图,它主要做几件事情: 组件化 利用 props 形成 ...
- reactive streams的Mono及Flux
实例 Mono @Testpublic void testMonoBasic(){Mono.fromSupplier(() -> "Hello").subscribe(Sys ...
最新文章
- python输入输出-python输入与输出
- 如何搭建一套融资租赁业务系统
- jQuery.ajaxPrefilter()函数的使用
- 台式计算机哪款好,台式一体机电脑哪款好
- 【AI视野·今日CV 计算机视觉论文速览 第188期】Wed, 23 Dec 2020
- Go语言的IO库那么多,我该怎么选?
- 博达路由器如何配置互联网ip_如何成为技术大牛第七步——路由器下接交换机单臂路由配置方法...
- 华为nova 8 Pro王者荣耀定制版曝光:内置小鲁班定制主题 电池盖镭雕小鲁班
- 腾讯会议开放API接口,为企业打造专属的“腾讯会议”
- 随手记_英语_学术写作_标点符号的使用
- 【深度学习】损失函数记录
- Codejock Toolkit工具包专业版
- 艾永亮:这家酒店如何让你毫不犹豫点上五星好评?
- GPS在无人驾驶中的定位作用与不足
- 微信第三方平台服务器,微信三方平台接入
- Stripe支付流程
- Odoo发邮件被服务器退回
- MySQL关系一对多一对一多对多
- 怎么把html文档转换成wps,怎么把wps文档转换成word文档
- Urlrewrite(url地址重写)和UrlRewriteFilter
热门文章
- Oracle-index索引解读
- matlab 添加环境变量,CentOS 添加环境变量的三种方法
- js对象与字符串相互转换
- bug ava.sql.SQLException: No more data to read from socket
- python 相交链表
- QT5实践:菜单窗口实现图像打开浏览、存盘
- java 面试题 简书_java面试题
- 跳转路径时资源路径加/和不加/的区别
- 【c++】23.【函数指针】定义? 为什么不直接调用函数而要使用函数指针?
- 初学Java Web(6)——JSP学习总结