文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android学习之Flux架构入门

2022-06-06 07:52

关注

Flux 架构介绍

Flux 架构 被Facebook使用来构建他们的客户端web应用。跟Clean Architecture一样,它不是为移动应用设计的,但是它的特性和简单可以让我们很好的在安卓项目中采用。

Flux模式最大的特点是单向的数据流,它的UI状态更新模式继承了MVC模式的设计思想。Flux并不是具体的框架,而是一套处理UI问题的模式,Android Flux同样不是具体的框架,你不需要导入或者集成任何新的代码就可以使用,而你需要做的事情是了解这套思想、遵循这种开发模式,查看我们提供的Android代码示例,写自己的代码。

要理解Flux,有两个关键的特点

1、数据流总是单向的

      一个单向的数据流 是 Flux 架构的核心,也是它简单易学的原因。就如下面讨论的,在进行应用测试的时候,它提供了非常大的帮助。

2、应用被分成三个主要部分:

     . View: 应用的界面。这里创建响应用户操作的

action

     . Dispatcher: 中心枢纽,传递所有的

action
,负责把它们运达每个
Store

     . Store: 维护一个特定

application domain
的状态。它们根据当前状态响应
action
,执行业务逻辑,同时在完成的时候发出一个
change
事件。这个事件用于
view
更新其界面。

     这三个部分都是通过

Action
来通信的:一个简单的基本对象,以类型来区分,包含了和操作相关的数据。

Flux Android 架构

在安卓开发中使用Flux设计规范的目的是建立一个在简单性与易扩展易测试之间都比较平衡的架构。

第一步是找到Flux元素和安卓app组件之间的映射。

其中两个元素非常容易找到与实现。

View: Activity o
或者
Fragment

Dispatcher: 
一个事件总线( event bus),在我的例子中将使用Otto,但是其它任何实现都应该是ok的。

Actions

Actions
也不复杂。它们的实现和
POJO
一样简单,有两个主要属性:

     1、Type: 一个String,定义了事件的类型。

     2、Data: 一个map,装载了本次操作。

Store是Flux理论中最难的部分。

Stores
响应
Dispatcher
发出的
Action
,执行业务逻辑并发送
change
事件。
Stores
的唯一输出是这单一的事件:
change
。其它对
Store
内部状态感兴趣的组件必须监听这个事件,同时使用它获取需要的数据。最后,
stores
必须对外公开一个获取
application
状态的接口。这样,
view
元素可以查询
Stores
然后相应的更新UI。

这里通过一个简单的小demo来讲述整个流程。我们的界面上有一个

Button
和一个
TextView
,点击
Button
后让
TextView
显示出文字。常规的实现,直接在
Activity
中完成逻辑,
MVP
模式,在
Presenter
层来进行,对于Flux架构,我们要怎么实现呢。通过上图我们可以看到,
View
会产生
Action
,然后被
Dispatcher
进行调度,经过
Store
相应处理,将数据显示出来。

如何产生Action

首先要知道

Action
是什么样


public class Action {
  private final String type;
  private final HashMap<String, Object> data;
  public Action(String type, HashMap<String, Object> data) {
    this.type = type;
    this.data = data;
  }
  public static Builder type(String type) {
    return new Builder().with(type);
  }
  public String getType() {
    return type;
  }
  public HashMap getData() {
    return data;
  }
  public static class Builder {
    private String type;
    private HashMap<String, Object> data;
    Builder with(String type) {
      if(type == null) {
        throw new IllegalArgumentException("Type may not be null.");
      }
      this.type = type;
      this.data = new HashMap<>();
      return this;
    }
    public Builder bundle(String key, Object value) {
      if (key == null) {
        throw new IllegalArgumentException("Key may not be null.");
      }
      if(value == null) {
        throw new IllegalArgumentException("Value may not be null.");
      }
      data.put(key, value);
      return this;
    }
    public Action build() {
      if (TextUtils.isEmpty(type)) {
        throw new IllegalArgumentException("At least one key is required.");
      }
      return new Action(type, data);
    }
  }
}

每一个

Action
有两个属性,一个来标记
Type
,另一个字段来存储传送的数据,通过
Map
来存放。

对于

Action Type
,我们可以通过一个接口或者类来进行记录,将所有的类型保存在其中。方便我们的调用。


public interface ShowActions {
  String TODO_SHOW = "todo-show";
  String GET_TEXT = "get-text";
}

如何创建

Action
,定义一个类,专门用来根据我们可能会出现的各种
View
的事件,定义出来各种
Action


public class ActionsCreator {
  private static ActionsCreator instance;
  final Dispatcher mDispatcher;
  ActionsCreator(Dispatcher dispatcher){
    mDispatcher = dispatcher;
  }
  public static ActionsCreator get(Dispatcher dispatcher) {
    if (instance == null) {
      instance = new ActionsCreator(dispatcher);
    }
    return instance;
  }
  public void create(String text) {
    mDispatcher.dispatch(ShowActions.TODO_SHOW, ShowActions.GET_TEXT, text);
  }

在我们准备用

ActionsCreator
来创建
Action
的时候,我们并没有直接
new Action
这种方式来做,而是将其通过调度器,对其进行了分发。这里的事件分发,我们使用的是
Otto
Bus
来进行事件的分发。


public class Dispatcher {
  private final Bus bus;
  private static Dispatcher instance;
  Dispatcher(Bus bus){
    this.bus = bus;
  }
  public static Dispatcher get(Bus bus) {
    if (instance == null) {
      instance = new Dispatcher(bus);
    }
    return instance;
  }
  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(TextUtils.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");
    }
    Action.Builder actionBuilder = Action.type(type);
    for (int i = 0; i < data.length; i++) {
      String key = (String) data[i++];
      Object value = data[i++];
      actionBuilder.bundle(key, value);
    }
    post(actionBuilder.build());
  }
  private boolean isEmpty(String type) {
    return TextUtils.isEmpty(type);
  }
  private void post(final Object event) {
    bus.post(event);
  }
}

在调度的过程中,我们将传递进来的数据进行一个解析,然后根据数据创建出相应的

Action
,然后对
Action
进行分发,这个时候关注了相应的
Action
Store
就会开始根据相应的
Action
开始执行相应的操作。在
Store
中,声明了一个抽象方法
onAction
来负责进行对于
Action
的判断和分发,然后定义了
StoreChangeEvent
接口作为事件变化,当有变化的时候,通过这个进行传递,我们可以自己实现这个接口,然后在里面添加一些方法和字段用来携带数据。


public abstract class Store {
  final Dispatcher mDispatcher;
  protected Store(Dispatcher dispatcher) {
    this.mDispatcher = dispatcher;
  }
  void emitStoreChange() {
    mDispatcher.emitChange(changeEvent());
  }
  abstract StoreChangeEvent changeEvent();
  public abstract void onAction(Action action);
  public interface StoreChangeEvent {}
}

我们自定义的Store类


public class ShowStore extends Store {
  private static ShowStore instance;
  private String showText;
  public ShowStore(Dispatcher dispatcher){
    super(dispatcher);
  }
  public static ShowStore get(Dispatcher dispatcher) {
    if (instance == null) {
      instance = new ShowStore(dispatcher);
    }
    return instance;
  }
  @Subscribe
  public void onAction(Action action) {
    switch (action.getType()) {
      case ShowActions.TODO_SHOW :
        showText = ((String)action.getData().get(ShowActions.GET_TEXT));
        Log.i("showText", showText);
        emitStoreChange();
        break;
      default:
        break;
    }
  }
  public String getShowText(){
    return showText;
  }
  @Override
  StoreChangeEvent changeEvent() {
    return new ShowChangeEvent();
  }
  public class ShowChangeEvent implements StoreChangeEvent {
  }
}

然后我们在

View
也就是
Activity
中订阅了变化时间的方法,这个时候就可以实现对于
View
中的数据的一个动态更新。


 @Subscribe
  public void showText (ShowStore.ShowChangeEvent event){
    mTextView.setText(mShowStore.getShowText());
   }

总结

通过Flux架构,使用的流程是,我们的View的事件会携带数据,通过一个ActionsCreate创建一个Type的Action,实际完成过程是在Dispatcher的dispatch中,然后再将这个Action丢给订阅了该Action的Store方法中,在这里完成各种逻辑,处理,甚至是可以发起网络请求获取数据,处理完成,可以将结果封装成一个事件,然后这个事件会再次通过调度器中的emitChangeEvent将事件传递给订阅了该事件的函数,而这个接收响应事件的函数被我们定义在我们View中,从而实现对于我们View的更新。以上就是本文的全部内容了,希望本文的内容对大家学习Flux架构有所帮助。

您可能感兴趣的文章:六款值得推荐的android(安卓)开源框架简介Android Retrofit 2.0框架上传图片解决方案简略分析Android的Retrofit应用开发框架源码举例讲解Android应用开发中OTTO框架的基本使用Android通用流行框架大全【整理】Android之使用Android-query框架开发实战(二)Android中XUtils3框架使用方法详解(一)Android AndBase框架使用封装好的函数完成Http请求(三)Android最基本的异步网络请求框架


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯