Facebook.png今天想和大家分享一下Flux,Flux是Facebook用来构建Web应用的架构,目前在React中被广泛使用。有这几点需要注意,Flux是模式而不是框架,是单向数据流,是MVC最好的实践。 至于为什么要使用Flux,我们可以看一个Facebook遇到的问题。
一开始,产品需求是聊天信息在右下角的chat View显示,如果用户没有点击,右上角出现红色标示,后来产品需要在中间的View中显示,如果已经被用户看到,则右上角不出现红色标示,一段时间之后,产品又需要在左边新增一个通讯录列表,可以显示最近的聊天信息,如果用户看到,则右上角不出现红色标示。(没有看错,就是如此让人不省心,哈哈。)
产品结构如下:
然后我们看下代码:
Chat Code.png我们可以看到,随着产品需求不断地累加,代码块越来越臃肿,很不利于维护,于是,Facebook推出了Flux,我们来看下Flux结构:
Flux结构各模块的介绍:
- View:视图层
- Action(动作):视图层发出的消息
- Dispatcher(派发器):接收、派遣Action
- Store(数据层):接受派遣的Action,执行业务逻辑,提醒Views更新
我们来看看在Android中如何使用,例子是一个TODO App,输入Todo内容,点击添加按钮,显示输入的Todo列表:
ToDo_App.pngTodoActionCreator
Action生成器,创建CREATE和GET_ALL Action
public class TodoActionCreator {
public static final String ID = "id";
public static final String TEXT = "text";
public static final int ACTION_CREATE = 0;
public static final int ACTION_GET_ALL = 1;
private Dispatcher dispatcher;
......
public void create(String text) {
dispatcher.dispatch(ACTION_CREATE, TEXT, text);
}
public void getAll(){
dispatcher.dispatch(ACTION_GET_ALL);
}
}
Dispatcher
public class Dispatcher {
private static Dispatcher dispatcher;
private Store.OnStoreChangeListener onStoreChangeListener;
public Dispatcher(Store.OnStoreChangeListener onStoreChangeListener) {
this.onStoreChangeListener = onStoreChangeListener;
}
......
public void dispatch(int type, Object... data){
HashMap<String, Object> hashMap = new HashMap<>();
int i = 0;
while (i < data.length) {
String key = (String) data[i++];
Object value = data[i++];
hashMap.put(key, value);
}
Action action = new Action(type, hashMap);
if (!isTodoStore(action)) {
return;
}
Store store;
if (isTodoStore(action)) {
store = new TodoStore(onStoreChangeListener);
store.onAction(new Action(type, hashMap));
}
}
private boolean isTodoStore(Action action) {
return action.getType() == TodoActionCreator.ACTION_GET_ALL || action.getType() == TodoActionCreator.ACTION_CREATE;
}
}
TodoStore
public class TodoStore extends Store{
public TodoStore(OnStoreChangeListener onStoreChangeListener) {
super(onStoreChangeListener);
}
@Override
public void onAction(Action action) {
switch (action.getType()){
case TodoActionCreator.ACTION_CREATE:
create((String) action.getHashMap().get(TodoActionCreator.TEXT));
emitStoreChange();
break;
case TodoActionCreator.ACTION_GET_ALL:
emitStoreChange();
break;
}
}
@Override
StoreChangeEvent changeEvent() {
StoreChangeEvent storeChangeEvent = new StoreChangeEvent();
storeChangeEvent.value = TodoRepositories.getTodos();
return storeChangeEvent;
}
private void create(String text) {
TodoRepositories.getTodos().add(new Todo(new Random().nextInt(), text));
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements Store.OnStoreChangeListener, View.OnClickListener{
private RecyclerView rvContent;
private EditText etTodo;
private Button btnAdd;
private ContentAdapter mContentAdapter;
private TodoActionCreator todoActionCreator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvContent = (RecyclerView) findViewById(R.id.rvContent);
rvContent.setLayoutManager(new LinearLayoutManager(this));//这里用线性显示 类似于listview
etTodo = (EditText) findViewById(R.id.etTodo);
btnAdd = (Button) findViewById(R.id.btnAdd);
btnAdd.setOnClickListener(this);
mContentAdapter = new ContentAdapter(new ArrayList<Todo>(),this);
rvContent.setAdapter(mContentAdapter);
todoActionCreator = TodoActionCreator.get(Dispatcher.get(this));
todoActionCreator.getAll();
}
@Override
public void OnStoreChange(Store.StoreChangeEvent storeChangeEvent) {
mContentAdapter.update((ArrayList<Todo>) storeChangeEvent.value);
mContentAdapter.notifyDataSetChanged(); }
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnAdd:
String text = etTodo.getText().toString();
todoActionCreator.create(text);
etTodo.setText("");
break;
}
}}
代码链接: http://pan.baidu.com/s/1c1oovss 密码: 9jnk
VS MVC
我们可以拿MVC比较一下,理想中MVC如下:
MVC_理想.png但在使用过程,一不小心就增加了View和Model之间的交互,导致Model和View之间的错综复杂,不利于维护和测试。
MVC_现实.png MVC结构.png而Flux则可以维持数据的单向性,如下:
Flux结构.png总结
Flux优点
- Improved data consistency 改善数据统一
- Easier to pinpoint root of bug 方便找到bug
- More meaningful unit tests 产生更多有意义的单元测试
Flux缺点
- Dispatcher 容易臃肿,复杂
- 代码过于模板化
- 移植现有代码比较困难
参考
原始地址: http://www.jianshu.com/p/d6f9d2ee64a2,欢迎关注我的微博
网友评论