Slide 1

Slide 1 text

Redux for Android Elliott Chenger sli.do#3073

Slide 2

Slide 2 text

Don’t Redux because it‘s the “cool” thing to do @echenger sli.do#3073

Slide 3

Slide 3 text

“It Depends” Is The Answer To Your Android Question - Sam Edwards MVWTF: Demystifying Architecture Patterns - Adam McNeilly @echenger sli.do#3073

Slide 4

Slide 4 text

Why did we choose Redux? @echenger sli.do#3073

Slide 5

Slide 5 text

Architectural Goals @echenger sli.do#3073

Slide 6

Slide 6 text

Clear Responsibility @echenger sli.do#3073

Slide 7

Slide 7 text

Testability @echenger sli.do#3073

Slide 8

Slide 8 text

Easy to Debug @echenger sli.do#3073

Slide 9

Slide 9 text

State Management @echenger sli.do#3073

Slide 10

Slide 10 text

User’s State @echenger sli.do#3073

Slide 11

Slide 11 text

@echenger sli.do#3073

Slide 12

Slide 12 text

@echenger sli.do#3073

Slide 13

Slide 13 text

@echenger sli.do#3073

Slide 14

Slide 14 text

What are possible solutions? @echenger sli.do#3073

Slide 15

Slide 15 text

Modern Architectures M V C M V P M V I M V V M @echenger sli.do#3073

Slide 16

Slide 16 text

MVP Model View Presenter @echenger sli.do#3073

Slide 17

Slide 17 text

MVP Presenter Model View State @echenger sli.do#3073

Slide 18

Slide 18 text

MVP @echenger sli.do#3073

Slide 19

Slide 19 text

MVP @echenger sli.do#3073

Slide 20

Slide 20 text

Redux @echenger sli.do#3073

Slide 21

Slide 21 text

Redux @echenger Presentation Layer Store State sli.do#3073

Slide 22

Slide 22 text

Centralized State @echenger sli.do#3073

Slide 23

Slide 23 text

Presentation Layer Store State @echenger sli.do#3073

Slide 24

Slide 24 text

Presentation Layer Store State Login Feed Inbox Profile List Detail @echenger sli.do#3073

Slide 25

Slide 25 text

Unidirectional Data Flow @echenger sli.do#3073

Slide 26

Slide 26 text

Presentation Layer Store State Login Feed Inbox Profile List Detail dispatch() onStateChanged() @echenger sli.do#3073

Slide 27

Slide 27 text

Redux Terminology @echenger sli.do#3073

Slide 28

Slide 28 text

Presentation Layer Store State @echenger sli.do#3073

Slide 29

Slide 29 text

Presentation Layer Store State Middleware Reducer Dispatch an Action Subscribe
 to changes @echenger sli.do#3073

Slide 30

Slide 30 text

App State @echenger sli.do#3073

Slide 31

Slide 31 text

What the state represents not how it is displayed @echenger sli.do#3073

Slide 32

Slide 32 text

@echenger sli.do#3073

Slide 33

Slide 33 text

@echenger sli.do#3073

Slide 34

Slide 34 text

data class AppState(val firstName: String, val lastName: String, val phoneNumber: String) @echenger sli.do#3073

Slide 35

Slide 35 text

Actions @echenger sli.do#3073

Slide 36

Slide 36 text

val searchAction = SetSearchText(searchTerm) store.dispatch(searchAction) @echenger sli.do#3073

Slide 37

Slide 37 text

data class SetSearchText(val searchTerm: String) : Action @echenger sli.do#3073

Slide 38

Slide 38 text

object ExecuteSearch : Action @echenger sli.do#3073

Slide 39

Slide 39 text

Reducers @echenger sli.do#3073

Slide 40

Slide 40 text

Update State @echenger sli.do#3073

Slide 41

Slide 41 text

override fun reduce(state: AppState, action: Action?): AppState { } @echenger sli.do#3073

Slide 42

Slide 42 text

override fun reduce(state: AppState, action: Action?): AppState { return when (action) { is SetSearchText -> { return state.copy(searchTerm = searchTerm) } else -> state } } @echenger sli.do#3073

Slide 43

Slide 43 text

return state.copy(searchTerm = searchTerm) @echenger sli.do#3073

Slide 44

Slide 44 text

Inverted Reducer @echenger sli.do#3073

Slide 45

Slide 45 text

override fun reduce(state: AppState, action: Action?): AppState { return when (action) { is SetSearchText -> { return state.copy(searchTerm = searchTerm) } is ExecuteSearch -> { return state.copy(isLoading = true) } is ImageSearchResponseAction -> { return state.copy( isLoading = false, imageCollection = imageCollection ) } else -> state } } @echenger sli.do#3073

Slide 46

Slide 46 text

interface Reducible { fun reduce(state: AppState): AppState } @echenger sli.do#3073

Slide 47

Slide 47 text

override fun reduce(state: AppState, action: Action?): AppState { return when (action) { is Reducible -> { action.reduce(state) } else -> state } } @echenger sli.do#3073

Slide 48

Slide 48 text

data class SetSearchText(val searchTerm: String) : ListAction(), Reducible { override fun reduce(state: AppState): AppState { return state.copy(searchTerm = searchTerm) } } class ExecuteSearch : ListAction(), Reducible { override fun reduce(state: AppState): AppState { return state.copy(isLoading = true) } } data class ImageSearchResponseAction(val imageCollection: ImageCollection) : ListAction(), Reducible { override fun reduce(state: AppState): AppState { return state.copy( isLoading = false, imageCollection = imageCollection ) } } @echenger sli.do#3073

Slide 49

Slide 49 text

Presentation Layer @echenger sli.do#3073

Slide 50

Slide 50 text

Presentation Layer Store State Middleware Reducer @echenger sli.do#3073

Slide 51

Slide 51 text

Presentation Layer Store State Middleware Reducer @echenger sli.do#3073

Slide 52

Slide 52 text

Presentation Layer Store Creates View Displayed UI Model @echenger sli.do#3073

Slide 53

Slide 53 text

ViewModel Store State Middleware Reducer Activity/Fragment LiveData State UI Model @echenger sli.do#3073

Slide 54

Slide 54 text

class ListViewModel(application: Application) : AndroidViewModel(application), StoreSubscriber { val uiModelLiveData = MutableLiveData() private val store: StoreType = (application as App).store init { store.subscribe(this) } fun onSearch(searchTerm: String) { val searchAction = SetSearchText(searchTerm) store.dispatch(searchAction) } override fun newState(state: AppState) { val state = store.state uiModelLiveData.value = MainUiModel.fromListState(state.listState) } override fun onCleared() { store.unsubscribe(this) } } @echenger sli.do#3073

Slide 55

Slide 55 text

init { store.subscribe(this) } @echenger sli.do#3073

Slide 56

Slide 56 text

override fun newState(state: AppState) { val state = store.state uiModelLiveData.value = MainUiModel.fromListState(state.listState) } @echenger sli.do#3073

Slide 57

Slide 57 text

Middleware @echenger sli.do#3073

Slide 58

Slide 58 text

Presentation Layer Store State Middleware Reducer @echenger sli.do#3073

Slide 59

Slide 59 text

class LoggingMiddleware : Middleware { override fun dispatch(store: Store, next: Dispatcher, action: Action): Action { Log.d("APP", "Dispatching $action") Log.d("APP", "SearchTeam before reducer ${store.state.listState.searchTerm}") val nextAction = next.dispatch(action) Log.d("APP", "SearchTeam after reducer ${store.state.listState.searchTerm}") return nextAction } } @echenger sli.do#3073

Slide 60

Slide 60 text

What is next()? @echenger sli.do#3073

Slide 61

Slide 61 text

Presentation Layer Store State Middleware Reducer @echenger sli.do#3073

Slide 62

Slide 62 text

Store State Reducer @echenger sli.do#3073

Slide 63

Slide 63 text

Store C A Reducer B next() next() next() @echenger sli.do#3073

Slide 64

Slide 64 text

Async Middleware @echenger sli.do#3073

Slide 65

Slide 65 text

Store State Middleware Reducer isLoading = true @echenger sli.do#3073 This slide won’t make sense until the talk video is up because it has lots of animations!

Slide 66

Slide 66 text

Store State Middleware Reducer isLoading = false
 response = data isLoading = true @echenger sli.do#3073

Slide 67

Slide 67 text

Wrap Up @echenger sli.do#3073

Slide 68

Slide 68 text

• Clear responsibility • Testability • Easier Debug-ability • State Management Redux @echenger sli.do#3073

Slide 69

Slide 69 text

Q&A @echenger sli.do#3073 http://bit.ly/3429SiQ