package cgeo.geocaching.utils; import android.app.Activity; import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import android.support.v4.app.Fragment; import java.lang.ref.WeakReference; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import io.reactivex.Maybe; import io.reactivex.Observable; import io.reactivex.Scheduler; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposables; import io.reactivex.functions.Consumer; import io.reactivex.functions.Predicate; import io.reactivex.internal.schedulers.RxThreadFactory; import io.reactivex.schedulers.Schedulers; public class AndroidRxUtils { public static final Scheduler computationScheduler = Schedulers.computation(); public static final Scheduler networkScheduler = Schedulers.from(Executors.newFixedThreadPool(10, new RxThreadFactory("network-"))); public static final Scheduler refreshScheduler = Schedulers.from(Executors.newFixedThreadPool(3, new RxThreadFactory("refresh-"))); private static final HandlerThread looperCallbacksThread = new HandlerThread("looper callbacks", Process.THREAD_PRIORITY_DEFAULT); static { looperCallbacksThread.start(); } public static final Looper looperCallbacksLooper = looperCallbacksThread.getLooper(); public static final Scheduler looperCallbacksScheduler = AndroidSchedulers.from(looperCallbacksLooper); private AndroidRxUtils() { // Utility class, not to be instantiated } public static <T> void andThenOnUi(final Scheduler scheduler, final Callable<T> background, final Consumer<T> foreground) { scheduler.createWorker().schedule(new Runnable() { @Override public void run() { try { final T value = background.call(); AndroidSchedulers.mainThread().createWorker().schedule(new Runnable() { @Override public void run() { try { foreground.accept(value); } catch (final Exception e) { Log.e("error when running the second part of andThenOnUi"); } } }); } catch (final Exception e) { Log.e("error when running the first part of andThenOnUi", e); } } }); } public static void andThenOnUi(final Scheduler scheduler, final Runnable background, final Runnable foreground) { scheduler.createWorker().schedule(new Runnable() { @Override public void run() { background.run(); AndroidSchedulers.mainThread().createWorker().schedule(foreground); } }); } public static <T> Observable<T> bindActivity(final Activity activity, final Observable<T> source) { final WeakReference<Activity> activityRef = new WeakReference<>(activity); return source.observeOn(AndroidSchedulers.mainThread()).takeWhile(new Predicate<T>() { @Override public boolean test(final T t) throws Exception { final Activity a = activityRef.get(); return a != null && !a.isFinishing(); } }); } public static <T> Maybe<T> bindActivity(final Activity activity, final Single<T> source) { final WeakReference<Activity> activityRef = new WeakReference<>(activity); return source.observeOn(AndroidSchedulers.mainThread()).filter(new Predicate<T>() { @Override public boolean test(final T t) throws Exception { final Activity a = activityRef.get(); return a != null && !a.isFinishing(); } }); } public static <T> Maybe<T> bindActivity(final Activity activity, final Maybe<T> source) { final WeakReference<Activity> activityRef = new WeakReference<>(activity); return source.observeOn(AndroidSchedulers.mainThread()).filter(new Predicate<T>() { @Override public boolean test(final T t) throws Exception { final Activity a = activityRef.get(); return a != null && !a.isFinishing(); } }); } public static <T> Observable<T> bindFragment(final Fragment fragment, final Observable<T> source) { final WeakReference<Fragment> fragmentRef = new WeakReference<>(fragment); return source.observeOn(AndroidSchedulers.mainThread()).filter(new Predicate<T>() { @Override public boolean test(final T t) throws Exception { final Fragment f = fragmentRef.get(); return f != null && f.isAdded() && !f.getActivity().isFinishing(); } }); } public static Disposable disposeOnCallbacksScheduler(final Runnable runnable) { return Disposables.fromRunnable(new Runnable() { @Override public void run() { looperCallbacksScheduler.scheduleDirect(runnable); } }); } }