Open ysyyork opened 7 years ago
Hi @ysyyork
The short answer is YES, the implementation should be thread safe. Each action is applied to reduce
function guarded by synchronised
block. So you can dispatch actions from any thread.
However, you may still have some problems with those. On each action, Reductor notifies all state listeners on the thread where the action was applied. That might be the problem sometimes, for example:
In Activity, UI code is listening for state updates and render it on each update.
If you will send any action from a background thread (for instance when data is loaded from a network) - render
will also be executed from that thread, leading to updating a UI not in main thread.
Usually, I solve that problem by enforcing all the actions to be propagated through Main Thread. I use simple middleware to do that:
public class MainThreadMiddleware<T> implements Middleware<T> {
private final Handler handler;
private MainThreadMiddleware() {
handler = new Handler(Looper.getMainLooper());
}
public static <T> MainThreadMiddleware<T> create() {
return new MainThreadMiddleware<>();
}
@Override
public Dispatcher create(Store<T> store, Dispatcher nextDispatcher) {
return action -> {
if (Looper.myLooper() != Looper.getMainLooper()) {
handler.post(() -> nextDispatcher.dispatch(action));
} else {
nextDispatcher.dispatch(action);
}
};
}
}
The idea is simple: if action is dispatched from other thread then Main looper - re-dispatch it!
So now I do not need to care about where to dispatch an action. I still need to care about not doing blocking operation in .subscribe(listener)
method, but that's where RxJava can help with .observeOn(scheduler)
method.
Thanks, this is really helpful. On Mon, May 15, 2017 at 05:21 Yaroslav notifications@github.com wrote:
Hi @ysyyork https://github.com/ysyyork
The short answer is YES, the implementation should be thread safe. Each action is applied to reduce function guarded by synchronised block. So you can dispatch actions from any thread.
However, you may still have some problems with those. On each action, Reductor notifies all state listeners on the thread where the action was applied. That might be the problem sometimes, for example:
In Activity, UI code is listening for state updates and render it on each update. If you will send any action from a background thread (for instance when data is loaded from a network) - render will also be executed from that thread, leading to updating a UI not in main thread.
Usually, I solve that problem by enforcing all the actions to be propagated through Main Thread. I use simple middleware to do that:
public class MainThreadMiddleware
implements Middleware { private final Handler handler; private MainThreadMiddleware() { handler = new Handler(Looper.getMainLooper()); } public static <T> MainThreadMiddleware<T> create() { return new MainThreadMiddleware<>(); } @Override public Dispatcher create(Store<T> store, Dispatcher nextDispatcher) { return action -> { if (Looper.myLooper() != Looper.getMainLooper()) { handler.post(() -> nextDispatcher.dispatch(action)); } else { nextDispatcher.dispatch(action); } }; }
}
The idea is simple: if action is dispatched from other thread then Main looper - re-dispatch it! So now I do not need to care about where to dispatch an action. I still need to care about not doing blocking operation in .subscribe(listener) method, but that's where RxJava can help with .observeOn(scheduler) method.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Yarikx/reductor/issues/28#issuecomment-301421979, or mute the thread https://github.com/notifications/unsubscribe-auth/AGYi5bQyKE-xzniN4kbAim2TSrHi20DFks5r6BkCgaJpZM4NZ_U3 .
Any suggestions on how to propagate actions dispatched from a background worker thread to the main thread for non-Android specific Java projects?
I plan to use dispatch action from a background service within a different thread. Is this implementation thread safe or I have to do it myself? Thanks.