├── .gitignore ├── AndroidFlux.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── flux │ │ └── android │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── flux │ │ │ └── android │ │ │ ├── MainActivity.java │ │ │ ├── actions │ │ │ ├── Action.java │ │ │ ├── ActionsCreator.java │ │ │ └── MessageAction.java │ │ │ ├── dispatcher │ │ │ └── Dispatcher.java │ │ │ ├── model │ │ │ └── Message.java │ │ │ └── stores │ │ │ ├── MessageStore.java │ │ │ └── Store.java │ └── res │ │ ├── drawable │ │ └── flux_logo.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── flux │ └── android │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | /gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | gradlew 11 | gradlew.bat 12 | -------------------------------------------------------------------------------- /AndroidFlux.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 这是一个极简的HelloWorld应用,主要用来展示如何在Android平台架构Flux应用。并提供一些基础代码,方便开发者直接Copy这些代码到自己的工程中,省掉重新造轮子的过程。接下来会一步步的解释这个应用是如何构建的。 2 | 3 | *Demo程序是用AndroidStudio开发的,假设你已经了解Android和AndroidStudioIDE,如果你已经很熟悉Android应用的开发,看完[AndroidFlux一览](http://androidflux.github.io/docs/overview.html#content)或许已经可以开发出基于Flux框架的应用,如果你并不熟悉Flux或者Android,务必先读完这篇文档* 4 | 5 | ## 源码结构 6 | 7 | 本着架构即目录的思想,让我们先看一下源码结构,整个的源码结构是这样的: 8 | 9 | ``` 10 | ➜ tree . 11 | . 12 | ├── MainActivity.java 13 | ├── actions 14 | │   ├── Action.java 15 | │   ├── ActionsCreator.java 16 | │   └── MessageAction.java 17 | ├── dispatcher 18 | │   └── Dispatcher.java 19 | ├── model 20 | │   └── Message.java 21 | └── stores 22 | ├── MessageStore.java 23 | └── Store.java 24 | ``` 25 | 26 | 这里包含4个目录和一个文件: 27 | 28 | 1. MainActivity.java Flux框架中的Controller-View部分,在Android中可以是Activity或者Fragment 29 | 2. actions Flux框架中的Action部分,存放不同类型的`XXXAction.java`和`ActionsCreator.java`文件 30 | 3. dispatcher Flux框架中的Dispatcher部分,存放 `Dispatcher.java` 文件,一个应用中只需要一个Dispatcher 31 | 4. model 存放各种业务逻辑相关的Model文件 32 | 5. stores Flux框架中的Stores部分,存在各种类型的 `XXXStore.java` 文件 33 | 34 | ## 创建一个Dispatcher 35 | 36 | 在AndroidFlux中Dispatcher是就是一个发布-订阅模式。Store会在这里注册自己的回调接口,Dispatcher会把Action分发到注册的Store,所以它会提供一些公有方法来注册监听和分发消息。 37 | ``` 38 | /** 39 | * Flux的Dispatcher模块 40 | * Created by ntop on 18/12/15. 41 | */ 42 | public class Dispatcher { 43 | private static Dispatcher instance; 44 | private final List stores = new ArrayList<>(); 45 | 46 | public static Dispatcher get() { 47 | if (instance == null) { 48 | instance = new Dispatcher(); 49 | } 50 | return instance; 51 | } 52 | 53 | Dispatcher() {} 54 | 55 | public void register(final Store store) { 56 | stores.add(store); 57 | } 58 | 59 | public void unregister(final Store store) { 60 | stores.remove(store); 61 | } 62 | 63 | public void dispatch(Action action) { 64 | post(action); 65 | } 66 | 67 | private void post(final Action action) { 68 | for (Store store : stores) { 69 | store.onAction(action); 70 | } 71 | } 72 | } 73 | ``` 74 | Dispatcher对外仅暴露3个公有方法: 75 | 76 | 1. register(final Store store) 用来注册每个Store的回调接口 77 | 2. unregister(final Store store) 用来接触Store的回调接口 78 | 3. dispatch(Action action) 用来触发Store注册的回调接口 79 | 80 | 这里仅仅用一个`ArrayList`来管理Stores,对于一个更复杂的App可能需要精心设计数据结构来管理Stores组织和相互间的依赖关系。 81 | 82 | ## 创建Stores 83 | 84 | 这里使用[EventBus](http://square.github.io/otto/)来实现Store,EventBus的主要功能是用来给Controller-View发送`change`事件: 85 | ``` 86 | /** 87 | * Flux的Store模块 88 | * Created by ntop on 18/12/15. 89 | */ 90 | public abstract class Store { 91 | private static final Bus bus = new Bus(); 92 | 93 | protected Store() { 94 | } 95 | 96 | public void register(final Object view) { 97 | this.bus.register(view); 98 | } 99 | 100 | public void unregister(final Object view) { 101 | this.bus.unregister(view); 102 | } 103 | 104 | void emitStoreChange() { 105 | this.bus.post(changeEvent()); 106 | } 107 | 108 | public abstract StoreChangeEvent changeEvent(); 109 | public abstract void onAction(Action action); 110 | 111 | public class StoreChangeEvent {} 112 | } 113 | ``` 114 | 抽象的Store类,提供了一个主要的虚方法 `void onAction(Action action)` ,这个方法是注册在Dispatcher里面的回调接口,当Dispatcher有数据派发过来的时候,可以在这里处理。 115 | 116 | 下面看一下更具体的和业务相关的MessageStore类: 117 | 118 | ``` 119 | /** 120 | * MessageStore类主要用来维护MainActivity的UI状态 121 | * Created by ntop on 18/12/15. 122 | */ 123 | public class MessageStore extends Store { 124 | private static MessageStore singleton; 125 | private Message mMessage = new Message(); 126 | 127 | public MessageStore() { 128 | super(); 129 | } 130 | 131 | public String getMessage() { 132 | return mMessage.getMessage(); 133 | } 134 | 135 | @Override 136 | @Subscribe 137 | public void onAction(Action action) { 138 | switch (action.getType()) { 139 | case MessageAction.ACTION_NEW_MESSAGE: 140 | mMessage.setMessage((String) action.getData()); 141 | break; 142 | default: 143 | } 144 | emitStoreChange(); 145 | } 146 | 147 | 148 | @Override 149 | public StoreChangeEvent changeEvent() { 150 | return new StoreChangeEvent(); 151 | } 152 | } 153 | ``` 154 | 155 | 在这里实现了 `onAction(Action action)` 方法,并用一个`switch`语句来路由各种不同的Action类型。同时维护了一个结构 `Message.java` 类,这个类用来记录当前要显示的消息。Store类只能通过Dispatcher来更新(不要提供`setter`方法),对外仅暴露各种`getter`方法来获取UI状态。这里用`String getMessage()`方法来获取具体的消息。 156 | 157 | ## 在Controller-View里面处理“change”事件 158 | 159 | 在Android中,Flux的Controller-View对应于Activity或者Fragment,我们需要在这里注册Strore发生改变的事件通知,以便在Store变化的时候重新绘制UI。 160 | 161 | ``` 162 | /** 163 | * Flux的Controller-View模块 164 | * Created by ntop on 18/12/15. 165 | */ 166 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 167 | private EditText vMessageEditor; 168 | private Button vMessageButton; 169 | private TextView vMessageView; 170 | 171 | private Dispatcher dispatcher; 172 | private ActionsCreator actionsCreator; 173 | private MessageStore store; 174 | 175 | @Override 176 | protected void onCreate(Bundle savedInstanceState) { 177 | super.onCreate(savedInstanceState); 178 | setContentView(R.layout.activity_main); 179 | initDependencies(); 180 | setupView(); 181 | } 182 | 183 | @Override 184 | protected void onDestroy() { 185 | super.onDestroy(); 186 | dispatcher.unregister(store); 187 | } 188 | 189 | private void initDependencies() { 190 | dispatcher = Dispatcher.get(); 191 | actionsCreator = ActionsCreator.get(dispatcher); 192 | store = new MessageStore(); 193 | dispatcher.register(store); 194 | } 195 | 196 | private void setupView() { 197 | vMessageEditor = (EditText) findViewById(R.id.message_editor); 198 | vMessageView = (TextView) findViewById(R.id.message_view); 199 | vMessageButton = (Button) findViewById(R.id.message_button); 200 | vMessageButton.setOnClickListener(this); 201 | } 202 | 203 | @Override 204 | public void onClick(View view) { 205 | int id = view.getId(); 206 | if (id == R.id.message_button) { 207 | if (vMessageEditor.getText() != null) { 208 | actionsCreator.sendMessage(vMessageEditor.getText().toString()); 209 | vMessageEditor.setText(null); 210 | } 211 | } 212 | } 213 | 214 | private void render(MessageStore store) { 215 | vMessageView.setText(store.getMessage()); 216 | } 217 | 218 | @Override 219 | protected void onResume() { 220 | super.onResume(); 221 | store.register(this); 222 | } 223 | 224 | @Override 225 | protected void onPause() { 226 | super.onPause(); 227 | store.unregister(this); 228 | } 229 | 230 | @Subscribe 231 | public void onStoreChange(Store.StoreChangeEvent event) { 232 | render(store); 233 | } 234 | } 235 | ``` 236 | 237 | 这部分的代码比较多,首先在 `onCreatre(...)` 方法中初始化了依赖和需要的UI组件。最重要的是 `onStoreChange(...)` 方法,这个方法是注册在Store中回调(使用EventBus的`@Subscribe`注解标识),当Store发生变化的时候会触发这个方法,我们在这里调用`render()`方法重绘整个界面。 238 | 239 | ## 创建Action 240 | 241 | Action是简单的POJO类型,只提供两个字段:`type` 和 `data`, 分别记录Action的类型和数据。注意Action一旦创建是不可更改的, 242 | 所以它的字段类型修饰为`final`类型。 243 | 244 | ``` 245 | public class Action { 246 | private final String type; 247 | private final T data; 248 | 249 | Action(String type, T data) { 250 | this.type = type; 251 | this.data = data; 252 | } 253 | 254 | public String getType() { 255 | return type; 256 | } 257 | 258 | public T getData() { 259 | return data; 260 | } 261 | } 262 | ``` 263 | 下面是一个业务相关的Action实现: 264 | 265 | ``` 266 | public class MessageAction extends Action { 267 | public static final String ACTION_NEW_MESSAGE = "new_message"; 268 | 269 | MessageAction(String type, String data) { 270 | super(type, data); 271 | } 272 | } 273 | ``` 274 | 275 | 这个实现非常简单,仅仅多定义了一个Action类型字段:`public static final String ACTION_NEW_MESSAGE = "new_message"`。如你所见,Action都是这么简单的,不包含任何业务逻辑。 276 | 277 | ## 创建ActionCreator 278 | 279 | ActionCreator 是Flux架构中第“四”个最重要的模块(前三:Dispatcher、Store、View),这里实际上处理很多工作,提供有一个有语义的API,构建Action,处理网络请求等。 280 | 281 | ``` 282 | /** 283 | * Flux的ActionCreator模块 284 | * Created by ntop on 18/12/15. 285 | */ 286 | public class ActionsCreator { 287 | 288 | private static ActionsCreator instance; 289 | final Dispatcher dispatcher; 290 | 291 | ActionsCreator(Dispatcher dispatcher) { 292 | this.dispatcher = dispatcher; 293 | } 294 | 295 | public static ActionsCreator get(Dispatcher dispatcher) { 296 | if (instance == null) { 297 | instance = new ActionsCreator(dispatcher); 298 | } 299 | return instance; 300 | } 301 | 302 | public void sendMessage(String message) { 303 | dispatcher.dispatch(new MessageAction(MessageAction.ACTION_NEW_MESSAGE, message)); 304 | } 305 | } 306 | ``` 307 | 此处提供了一个 `sendMessage(String message)` ,就像名字暗示的那样,这个方法用来发送消息(到Store)。在方法内部,会创建一个`MessageAction`来封装数据和Action类型,并通过Dispatcher发送到Store。 308 | 309 | ## Model 310 | 无论是基于哪种框架的应用都需要Model模块,在这个简单的“HelloWorld”应用中,其实用一个String即可传递消息,但是为了架构的完整和更好的语义表达,定义一个Message类型封装一个String字段作为Model。 311 | 312 | 希望通过这个简单的HelloWorld应用,能够让你一窥Flux的面貌。如果你想更深入的了解在Android平台上应用Flux架构,可以查看我们的[Github站点](http://androidflux.github.io/)。 313 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.example.flux.android" 9 | minSdkVersion 15 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:22.2.0' 26 | compile 'com.android.support:design:22.2.0' 27 | compile 'com.squareup:otto:1.3.8' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/ntop/Tools/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/flux/android/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.EditText; 8 | import android.widget.TextView; 9 | 10 | import com.example.flux.android.stores.Store; 11 | import com.squareup.otto.Bus; 12 | import com.squareup.otto.Subscribe; 13 | 14 | import com.example.flux.android.actions.ActionsCreator; 15 | import com.example.flux.android.dispatcher.Dispatcher; 16 | import com.example.flux.android.stores.MessageStore; 17 | 18 | /** 19 | * Flux的Controller-View模块 20 | * Created by ntop on 18/12/15. 21 | */ 22 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 23 | private EditText vMessageEditor; 24 | private Button vMessageButton; 25 | private TextView vMessageView; 26 | 27 | private Dispatcher dispatcher; 28 | private ActionsCreator actionsCreator; 29 | private MessageStore store; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | initDependencies(); 36 | setupView(); 37 | } 38 | 39 | @Override 40 | protected void onDestroy() { 41 | super.onDestroy(); 42 | dispatcher.unregister(store); 43 | } 44 | 45 | private void initDependencies() { 46 | dispatcher = Dispatcher.get(); 47 | actionsCreator = ActionsCreator.get(dispatcher); 48 | store = new MessageStore(); 49 | dispatcher.register(store); 50 | } 51 | 52 | private void setupView() { 53 | vMessageEditor = (EditText) findViewById(R.id.message_editor); 54 | vMessageView = (TextView) findViewById(R.id.message_view); 55 | vMessageButton = (Button) findViewById(R.id.message_button); 56 | vMessageButton.setOnClickListener(this); 57 | } 58 | 59 | @Override 60 | public void onClick(View view) { 61 | int id = view.getId(); 62 | if (id == R.id.message_button) { 63 | if (vMessageEditor.getText() != null) { 64 | actionsCreator.sendMessage(vMessageEditor.getText().toString()); 65 | vMessageEditor.setText(null); 66 | } 67 | } 68 | } 69 | 70 | private void render(MessageStore store) { 71 | vMessageView.setText(store.getMessage()); 72 | } 73 | 74 | @Override 75 | protected void onResume() { 76 | super.onResume(); 77 | store.register(this); 78 | } 79 | 80 | @Override 81 | protected void onPause() { 82 | super.onPause(); 83 | store.unregister(this); 84 | } 85 | 86 | @Subscribe 87 | public void onStoreChange(Store.StoreChangeEvent event) { 88 | render(store); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/actions/Action.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.actions; 2 | 3 | /** 4 | * Created by ntop on 18/12/15. 5 | */ 6 | public class Action { 7 | private final String type; 8 | private final T data; 9 | 10 | Action(String type, T data) { 11 | this.type = type; 12 | this.data = data; 13 | } 14 | 15 | public String getType() { 16 | return type; 17 | } 18 | 19 | public T getData() { 20 | return data; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/actions/ActionsCreator.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.actions; 2 | 3 | import com.example.flux.android.dispatcher.Dispatcher; 4 | 5 | /** 6 | * Flux的ActionCreator模块 7 | * Created by ntop on 18/12/15. 8 | */ 9 | public class ActionsCreator { 10 | 11 | private static ActionsCreator instance; 12 | final Dispatcher dispatcher; 13 | 14 | ActionsCreator(Dispatcher dispatcher) { 15 | this.dispatcher = dispatcher; 16 | } 17 | 18 | public static ActionsCreator get(Dispatcher dispatcher) { 19 | if (instance == null) { 20 | instance = new ActionsCreator(dispatcher); 21 | } 22 | return instance; 23 | } 24 | 25 | public void sendMessage(String message) { 26 | dispatcher.dispatch(new MessageAction(MessageAction.ACTION_NEW_MESSAGE, message)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/actions/MessageAction.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.actions; 2 | 3 | /** 4 | * Created by ntop on 18/12/15. 5 | */ 6 | public class MessageAction extends Action { 7 | public static final String ACTION_NEW_MESSAGE = "new_message"; 8 | 9 | MessageAction(String type, String data) { 10 | super(type, data); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/dispatcher/Dispatcher.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.dispatcher; 2 | 3 | import com.example.flux.android.actions.Action; 4 | import com.example.flux.android.stores.Store; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List;; 8 | 9 | /** 10 | * Flux的Dispatcher模块 11 | * Created by ntop on 18/12/15. 12 | */ 13 | public class Dispatcher { 14 | private static Dispatcher instance; 15 | private final List stores = new ArrayList<>(); 16 | 17 | public static Dispatcher get() { 18 | if (instance == null) { 19 | instance = new Dispatcher(); 20 | } 21 | return instance; 22 | } 23 | 24 | Dispatcher() {} 25 | 26 | public void register(final Store store) { 27 | if (!stores.contains(store)) { 28 | stores.add(store); 29 | } 30 | } 31 | 32 | public void unregister(final Store store) { 33 | stores.remove(store); 34 | } 35 | 36 | public void dispatch(Action action) { 37 | post(action); 38 | } 39 | 40 | private void post(final Action action) { 41 | for (Store store : stores) { 42 | store.onAction(action); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/model/Message.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.model; 2 | 3 | /** 4 | * Created by ntop on 18/12/15. 5 | */ 6 | public class Message { 7 | private String mText; 8 | 9 | public Message(){} 10 | 11 | public Message(String text) { 12 | mText = text; 13 | } 14 | 15 | public String getMessage() { 16 | return mText; 17 | } 18 | 19 | public void setMessage(String text) { 20 | mText = text; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/stores/MessageStore.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.stores; 2 | 3 | import com.example.flux.android.actions.Action; 4 | import com.example.flux.android.actions.MessageAction; 5 | import com.example.flux.android.model.Message; 6 | import com.squareup.otto.Bus; 7 | import com.squareup.otto.Subscribe; 8 | 9 | /** 10 | * MessageStore类主要用来维护MainActivity的UI状态 11 | * Created by ntop on 18/12/15. 12 | */ 13 | public class MessageStore extends Store { 14 | private static MessageStore singleton; 15 | private Message mMessage = new Message(); 16 | 17 | public MessageStore() { 18 | super(); 19 | } 20 | 21 | public String getMessage() { 22 | return mMessage.getMessage(); 23 | } 24 | 25 | @Override 26 | @Subscribe 27 | public void onAction(Action action) { 28 | switch (action.getType()) { 29 | case MessageAction.ACTION_NEW_MESSAGE: 30 | mMessage.setMessage((String) action.getData()); 31 | break; 32 | default: 33 | } 34 | emitStoreChange(); 35 | } 36 | 37 | 38 | @Override 39 | public StoreChangeEvent changeEvent() { 40 | return new StoreChangeEvent(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/flux/android/stores/Store.java: -------------------------------------------------------------------------------- 1 | package com.example.flux.android.stores; 2 | 3 | import com.example.flux.android.actions.Action; 4 | import com.example.flux.android.dispatcher.Dispatcher; 5 | import com.squareup.otto.Bus; 6 | 7 | /** 8 | * Flux的Store模块 9 | * Created by ntop on 18/12/15. 10 | */ 11 | public abstract class Store { 12 | private static final Bus bus = new Bus(); 13 | 14 | protected Store() { 15 | } 16 | 17 | public void register(final Object view) { 18 | this.bus.register(view); 19 | } 20 | 21 | public void unregister(final Object view) { 22 | this.bus.unregister(view); 23 | } 24 | 25 | void emitStoreChange() { 26 | this.bus.post(changeEvent()); 27 | } 28 | 29 | public abstract StoreChangeEvent changeEvent(); 30 | public abstract void onAction(Action action); 31 | 32 | public class StoreChangeEvent {} 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/flux_logo.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 17 |