Slide 1

Slide 1 text

在你的 MOBILE 開發中使⽤用 REDUX
 USE REDUX TO ROCK YOUR MOBILE DEVELOPMENT Elvis Lin @mopcon
 2017-10-29

Slide 2

Slide 2 text

⼤大綱 • 常⾒見見的架構:MVC、MVP、MVVM • 3 Principle of Redux • Redux 的元件 • 範例例程式 • 如何測試

Slide 3

Slide 3 text

WHY NOT MVC? • 太多狀狀態 • 狀狀態維護困難 • 肥⼤大的 Controller • Model 跟 View 互動複雜

Slide 4

Slide 4 text

Event Controller /Activity Model Model Model Model Model View View View View View

Slide 5

Slide 5 text

MVP • 將 UI 更更新的邏輯抽到 Presenter • Activity / ViewController 只負責 event 轉發跟畫⾯面更更新 • Presenter 不相依於 Framework 的程式 • Reference: https://speakerdeck.com/elvismetaphor/ introduction-to-mv-whatever-in-android

Slide 6

Slide 6 text

Source: https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52

Slide 7

Slide 7 text

MVVM • 將 UI 的狀狀態保存在 ViewModel 中 • Activity / ViewController 透過 Data binding 或 Rx (observable) 跟 ViewModel 溝通 • ViewModel 不相依於 Framework 的程式 • Reference: https://speakerdeck.com/elvismetaphor/ implements-mvvm-in-android-with-data-binding

Slide 8

Slide 8 text

Source: https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52

Slide 9

Slide 9 text

REDUX 架構

Slide 10

Slide 10 text

REDUX 架構 • 單向資料流 • 所有的狀狀態只透過發送 action 做更更新

Slide 11

Slide 11 text

UNIDIRECTIONAL ARCHITECTURE

Slide 12

Slide 12 text

STORE/STATE 更更新的⽅方式

Slide 13

Slide 13 text

UNIDIRECTIONAL Source: http://www.michaelridland.com/xamarin/mvvm-mvc-is-dead-is-unidirectional-a-mvvm-mvc-killer/

Slide 14

Slide 14 text

Source: https://github.com/reactjs/redux/issues/653

Slide 15

Slide 15 text

REDUX PRINCIPLES

Slide 16

Slide 16 text

THREE PRINCIPLES (REDUX) • Single source of truth
 The state of your whole application is stored in an object tree within a single store. • State is read-only
 The only way to change the state is to emit an action. • Changes are made with pure functions
 Pure reducers specify how the state tree is transformed.

Slide 17

Slide 17 text

SINGLE SOURCE OF TRUTH • Traditional Style • 多個 Manager / DateStore 保存、維護所有資 料 • Redux Style • ⼀一個 Store/State 保存所有資料

Slide 18

Slide 18 text

STATE IS READ-ONLY • Traditional Style • Data/State是可變的(mutable) • Redux Style • State 是不可變的(immutable),⽤用新的 State 取代舊的 state

Slide 19

Slide 19 text

CHANGES ARE MADE WITH PURE FUNCTIONS • Functional: • Only generate output from input, doesn’t modify other states. • Y = f(x), • ex: squareRoot(4) = 2

Slide 20

Slide 20 text

CHANGES ARE MADE WITH PURE FUNCTIONS • Traditional Style • 改變 state 的 method 是有 side-effect 的 • Redux Style • Reducer 接受 current state,輸出 new state

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

WHY NOT MUTABLE STATE? • 需要⼿手動的去通知狀狀態的變化 • 資料/狀狀態會在我們不預期的時候發⽣生改變 • 非執⾏行行緒安全(Not thread safe) • 較難測試

Slide 23

Slide 23 text

REDUX

Slide 24

Slide 24 text

REDUX 的元件 • Store: dispatch action, and notify the subscriber • State: key the data of the app • Action: Define which should be modify, and provide necessary parameter • Reducer: Modify the state by the action • View/Controller/Presenter: Get the event and dispatch it to store

Slide 25

Slide 25 text

REDUX 更更新的流程(FLOW) • Store object holds and maintains the state • To change the state application can dispatch actions to Store • For each action Store compute new state using pure function f(s, a) (called reducer) • Store replace current state with new state

Slide 26

Slide 26 text

REDUX ARCH. Source: https://github.com/ReSwift/ReSwift

Slide 27

Slide 27 text

REDUCTOR: 
 REDUX LIBRARY (ANDROID)

Slide 28

Slide 28 text

REDUCTOR • Use Annotation to create boilerplate code • All the boilerplate is written by a machine

Slide 29

Slide 29 text

STATE @CombinedState
 @AutoValue
 public abstract class AppState {
 public abstract List notes();
 
 public abstract NotesFilter filter();
 
 public static TypeAdapter typeAdapter(Gson gson) {
 return new AutoValue_AppState.GsonTypeAdapter(gson);
 }
 
 public List getFilteredNotes() {
 List notes = this.notes();
 NotesFilter filter = this.filter();
 return Utils.filter(ConsPStack.from(notes), note ->
 filter == NotesFilter.ALL
 || filter == NotesFilter.CHECKED && note.checked
 || filter == NotesFilter.UNCHECKED && !note.checked);
 }
 }


Slide 30

Slide 30 text

ACTION @ActionCreator
 public interface NotesActions {
 String ADD_ACTION = "ADD_ITEM";
 String TOGGLE = "TOGGLE";
 String REMOVE_ITEM = "REMOVE_ITEM";
 
 @ActionCreator.Action(NotesActions.ADD_ACTION)
 Action add(int id, String content);
 
 @ActionCreator.Action(NotesActions.REMOVE_ITEM)
 Action remove(int id);
 
 @ActionCreator.Action(NotesActions.TOGGLE)
 Action toggle(int id);
 }


Slide 31

Slide 31 text

REDUCER @AutoReducer
 public abstract class NotesListReducer implements Reducer> {
 
 @AutoReducer.InitialState
 List initialState() {
 return TreePVector.empty();
 }
 
 @Action(value = NotesActions.ADD_ACTION,
 from = NotesActions.class)
 public List add(List state, int id, String content) {
 return TreePVector.from(state).plus(new Note(id, content, false));
 }
 
 
 
 public static NotesListReducer create() {
 return new NotesListReducerImpl();
 }
 }

Slide 32

Slide 32 text

Sample Code

Slide 33

Slide 33 text

– Reductor Example https://github.com/Yarikx/reductor

Slide 34

Slide 34 text

RESWIFT: 
 REDUX LIBRARY (IOS)

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

TESTING

Slide 37

Slide 37 text

重複的程式碼已經⾃自動產⽣生 • 只剩下 Data & Function • State: Data • Reducer: Function

Slide 38

Slide 38 text

STATE • Inherit to initialize data • Test the subclass of

Slide 39

Slide 39 text

REDUCER • Each method of a reducer is a pure functional method • So, It’s a piece of cake!

Slide 40

Slide 40 text

延伸問題 • 如何處理理非同步? • 使⽤用 midleware • ⾃自⼰己修改 reductor!! • 如何組合多個 Action? • 頻繁的 new state 造成 GC?

Slide 41

Slide 41 text

業界案例例

Slide 42

Slide 42 text

Pinterest KKday

Slide 43

Slide 43 text

CONTACT ME • @AndroidTaipei • Blog: https://blog.elvismetaphor.me • Slides: https://speakerdeck.com/elvismetaphor • GitHub: https://github.com/elvismetaphor

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

REFERENCE • Redux for Android. Predictable state container library for Java/Android
 https://github.com/Yarikx/reductor • Unidirectional data flow on Android using Kotlin
 https://speakerdeck.com/cesarvaliente/unidirectional-data- flow-on-android-using-kotlin

Slide 46

Slide 46 text

REFERENCE • Unidirectional Data Flow in Swift
 http://reswift.github.io/ReSwift/master/