Last active
May 9, 2019 06:30
-
-
Save jayrambhia/45f88628444952bacd674b24d0605bda to your computer and use it in GitHub Desktop.
Redux implementation in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class AppState(val searchState: SearchState = SearchState()) | |
class AppStore: Store<AppState>( | |
initialState = AppState(), | |
reducers = listOf(::reduceSearchState)) { | |
companion object { | |
val instance by lazy { | |
AppStore() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class AppState(val searchState: SearchState = SearchState()) | |
class AppStore: Store<AppState>( | |
initialState = AppState(), | |
reducers = listOf(::reduceSearchState), | |
middleware = listOf(::loggerMiddleware, ::searchMiddleware)) { | |
companion object { | |
val instance by lazy { | |
AppStore() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class SimpleStore<State>( | |
private val initialState: State, | |
private val reducers: List<Reducer<State>>): Store<State> { | |
private var currentState: State = initialState | |
private val subscriptions = arrayListOf<Subscription<State>>() | |
override fun getState() = currentState | |
override fun dispatch(action: Action) { | |
val newState = applyReducers(currentState, action) | |
if (newState == currentState) { | |
// No change in state | |
return | |
} | |
currentState = newState | |
subscriptions.forEach { it(currentState) } | |
} | |
private fun applyReducers(current: State, action: Action): State { | |
var newState = current | |
for (reducer in reducers) { | |
newState = reducer(newState, action) | |
} | |
return newState | |
} | |
override fun subscribe(subscription: Subscription<State>) { | |
subscriptions.add(subscription) | |
// notify subscription of the current state | |
subscription(state) | |
} | |
override fun unsubscribe(subscription: Subscription<State>) { | |
subscriptions.remove(subscription) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class SimpleStore<State>( | |
private val initialState: State, | |
private val reducers: List<Reducer<State>>): Store<State> { | |
private var currentState: State = initialState | |
private val subscriptions = arrayListOf<Subscription<State>>() | |
private fun dispatch(action: Action) { | |
val newState = applyReducers(currentState, action) | |
if (newState == currentState) { | |
// No change in state | |
return | |
} | |
currentState = newState | |
subscriptions.forEach { it(currentState, ::dispatch) } | |
} | |
override fun subscribe(subscription: Subscription<State>): Unsubscribe { | |
subscriptions.add(subscription) | |
// notify subscription of the current state | |
subscription(state, ::dispatch) | |
return { subscriptions.remove(subscription) } | |
} | |
// Rest of the code - reudcers and stuff. | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
abstract class SimpleStore<State>( | |
private val initialState: State, | |
private val reducers: List<Reducer<State>>, | |
private val middleware: List<Middleware>): Store<State> { | |
private var currentState: State = initialState | |
private val subscriptions = arrayListOf<Subscription<State>>() | |
private fun dispatch(action: Action) { | |
val newAction = applyMiddleware(currentState, action) | |
val newState = applyReducers(currentState, newAction) | |
if (newState == currentState) { | |
// No change in state | |
return | |
} | |
currentState = newState | |
subscriptions.forEach { it(currentState, ::dispatch) } | |
} | |
private fun applyMiddleware(state: State, action: Action): Action { | |
return next(0)(state, action, ::dispatch) | |
} | |
private fun next(index: Int): Next<State> { | |
if (index == middleware.size) { | |
// Last link of the chain. It just returns the action as is. | |
return { _, action, _ -> action } | |
} | |
return { state, action, dispatch -> middleware[index].invoke(state, action, dispatch, next(index+1)) } | |
} | |
// Rest of the code - reudcers and stuff. | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SearchFragment: Fragment() { | |
override fun onViewCreated(View view) { | |
super.onViewCreated(view) | |
// .. initialize views | |
AppStore.instance.subscribe(::render) | |
searchButton.setOnClickListener { | |
AppStore.instance.dispatch(Seaarch(queryEditText.getText().toString())) | |
} | |
clearButton.setOnClickListener { | |
AppStore.instance.dispatch(ClearSearch) | |
} | |
} | |
override fun onDestroyView() { | |
super.onDestroyView() | |
AppStore.instance.unsubscribe(::render) | |
} | |
private fun render(state: AppState) { | |
progressbar.show(state.loading) | |
clearButton.show(movies.size > 0) | |
searchButton.show(!state.loading) | |
queryEdittext.setText(state.query) | |
adapter.setMovies(movies) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SearchFragment: Fragment() { | |
private var dispatch: Dispatch? = null | |
private lateinit var unsubscribe: Unsubscribe | |
override fun onViewCreated(View view) { | |
super.onViewCreated(view) | |
// .. initialize views | |
unsubscribe = AppStore.instance.subscribe(::render) | |
searchButton.setOnClickListener { | |
dispatch?.invoke(Seaarch(queryEditText.getText().toString())) | |
} | |
clearButton.setOnClickListener { | |
dispatch?.invoke(ClearSearch) | |
} | |
} | |
override fun onDestroyView() { | |
super.onDestroyView() | |
unsubscribe.invoke() | |
dispatch = null | |
} | |
private fun render(state: AppState, dispatch: Dispatch) { | |
this.dispatch = dispatch | |
// .. rest of the code | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class SearchState(val loading: Boolean = false, val query: String = "", val movies: List<Movie> = listOf()) | |
object ClearSearch: Action | |
data class Search(val query: String): Action | |
data class LoadingSearch(val query: String): Action | |
data class SearchResultsLoaded(val query: String, val movies: List<Movie>): Action | |
fun reduceSearchState(state: AppState, action: Action): AppState { | |
return when(action) { | |
is ClearSearch -> state.copy(searchState = SearchState()) | |
is LoadingSearch -> state.copy(searchState = SearchState(loading = true, query = action.query)) | |
is SearchResultsLoaded -> state.copy(searchState = SearchState(query = action.query, loading = false, movies = action.movies)) | |
else -> state | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment