GeoThings / ReKotlin

Unidirectional Data Flow in Kotlin - Port of https://github.com/ReSwift/ReSwift to Kotlin
MIT License
80 stars 41 forks source link

Run Dispatch in a background thread #11

Open Dimillian opened 6 years ago

Dimillian commented 6 years ago

In a big app, with potentially a lot of actions, I want to be able to dispatch all my functions on a serialised specified or not thread. At the moment there is no "easy" way to add this functionality without writing your final implementation of Store again to just change the dispatch method.

What I'm doing in ReSwift is extend Store and create my own dispatch like this

extension Store {
    open func dispatchQueue(_ action: Action) {
        DispatchQueue.flux().async {
            self.dispatchFunction(action)
        }
    }
}
let FLUX_QUEUE = DispatchQueue(label: "com.glose.ios.store.queue")

extension DispatchQueue {
    public class func flux() -> DispatchQueue {
        return FLUX_QUEUE
    }
}

I don't see any way to do that that in Kotlin and ReKotlin without writing your whole class Store again.

I'm I missing something?

ambientlight commented 6 years ago

@Dimillian: Sorry for being too late.

Redux dispatch is synchronous by design. Given you said you app has lots of actions - does it mean you have expensive logic inside your reducers?

Usually, the common good practice (citation needed) is to keep your reducers lightweight (mostly object assignments from passed actions), with complex logic moved inside the middleware which can be executed async and then dispatch another action when the asynch action completes. Such way can eliminate the need for asynchronous dispatch.

Dimillian commented 6 years ago

Of course it need to be synchronised, I've solved my problem, basically I've created new dispatch and subscribe top level functions which execute everything in a single thread executor. My goal was to run everything on the same queue, different from the UI thread, which is now the case. The only thing to remember is to run newState functions on the UI thread if necessary.

val dispatchExecutor: ExecutorService = Executors.newSingleThreadExecutor()

fun dispatch(action: Action) {
    dispatchExecutor.submit {
        store.dispatch(action)
    }
}

fun <SelectedState, S: StoreSubscriber<SelectedState>> subscribe(subscriber: S, transform: ((Subscription<AppState>) -> Subscription<SelectedState>)?)  {
    dispatchExecutor.submit {
        store.subscribe(subscriber, transform)
    }
}

fun <SelectedState> unsubscribe(subscriber: StoreSubscriber<SelectedState>) {
    dispatchExecutor.submit {
        store.unsubscribe(subscriber)
    }
}