public class Main { public static void main(String[] args) { /* PendingAction是解决经常遇到的“等待某些条件满足后执行”case的一种超轻量级的框架。 例如,某代码逻辑在绑定后台成功后执行一次/某代码逻辑在连上服务器后执行一次。注意如果要执行多次(即当成订阅模式使用)时, action handler的removeAfterRun要设置为false */ // 1. 首先,创建一个PendingAction对象。一般情况下,一个业务场景只有一个这样的对象。 PendingAction pendingAction = new PendingAction(); // 2. 创建action handler,表明当条件满足时,你要做些什么。 PendingAction.createActionHandler() .doOnce(() -> { // 这里写你要执行的代码 System.out.println("A doOnce called"); }) // .removeAfterRun(true) // 设置是否执行完一次就销毁。默认是。 .waitAll(Event.A, Event.B) // 等待 A B 全部执行(and) .waitOne(Event.E, Event.F) // 等待 E F 其中一个执行(or) .attachTo(pendingAction); // 将handler注入到之前创建的PendingAction对象中 System.out.println("add A"); pendingAction.addEvent(Event.A); System.out.println("add B"); // 运行完这一句后,A、B都执行过,上面的handler会执行,打印"A doOnce called" pendingAction.addEvent(Event.B); System.out.println("add C"); // 注意!运行完这一句后,A、B、C都执行过,如果removeAfterRun为false, // 那么上面的handler会执行,打印"A doOnce called" pendingAction.addEvent(Event.C); System.out.println("set C"); // 这里用了setEvent,表示重置内部的event状态,上面的A、B event会被清掉 pendingAction.setEvent(Event.C); System.out.println("remove BC"); // 可以remove掉指定的event pendingAction.removeEvent(Event.B, Event.C, Event.A); System.out.println("add E"); // 运行完这一句后,E或者F执行过。但是!由于默认removeAfterRun为true, // handler已经销毁,所以这里并不会打印"A doOnce called" pendingAction.addEvent(Event.E); System.out.println("clear"); pendingAction.clear(); } private enum Event { A, B, C, D, E, F, G } }
源码如下所示:
import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; public class PendingAction { private Set<Enum<?>> mEvents = new HashSet<>(); private List<ActionHandler> mActionHandlers = new ArrayList<>(); ///////////////////////////////////public/////////////////////////////////// public synchronized void addHandler(ActionHandler actionHandler) { mActionHandlers.add(actionHandler); if (runHandler(actionHandler) && actionHandler.mAutoRemove) { mActionHandlers.remove(actionHandler); } } public synchronized void addEvent(Enum<?> event) { mEvents.add(event); for (ActionHandler actionHandler : new ArrayList<>(mActionHandlers)) { if (runHandler(actionHandler) && actionHandler.mAutoRemove) { mActionHandlers.remove(actionHandler); } } } public synchronized void clear() { mEvents.clear(); mActionHandlers.clear(); } public synchronized void removeEvent(Enum<?> ... states) { mEvents.removeAll(Arrays.asList(states)); } public synchronized void setEvent(Enum<?> ... states) { mEvents.clear(); for (Enum<?> state : states) { addEvent(state); } } public synchronized Set<Enum<?>> getEvents() { return new HashSet<>(mEvents); } ////////////////////////////////////////////////////////////////////// public static synchronized ActionHandler createActionHandler() { ActionHandler newActionHandler = new ActionHandler(); return newActionHandler; } ///////////////////////////////////private/////////////////////////////////// private synchronized boolean runHandler(ActionHandler actionHandler) { if (actionHandler.isMatch(mEvents)) { actionHandler.run(); return true; } return false; } ///////////////////////////////////state/////////////////////////////////// public static class ActionHandler { private Runnable mRunnable; private List<MatchStrategy> mMatchStrategyList = new ArrayList<>(); private boolean mAutoRemove = true; private ActionHandler() { } public synchronized ActionHandler doOnce(Runnable runnable) { mRunnable = runnable; return this; } public synchronized ActionHandler waitAll(Enum<?> ... waitTargets) { Set<Enum<?>> targetSet = new HashSet<>(Arrays.asList(waitTargets)); mMatchStrategyList.add(collection -> collection.size() > 0 && targetSet.containsAll(collection)); return this; } public ActionHandler waitOne(Enum<?> ... waitTargets) { // 求交集,每次都新建一个 mMatchStrategyList.add(states -> { Set<Enum<?>> temp = new HashSet<>(Arrays.asList(waitTargets)); temp.retainAll(states); return temp.size() > 0; }); return this; } public synchronized ActionHandler removeAfterRun(boolean autoRemove) { mAutoRemove = autoRemove; return this; } public void attachTo(PendingAction action) { assert action != null; action.addHandler(this); } void run() { if (mRunnable != null) { mRunnable.run(); } } boolean isMatch(Set<Enum<?>> states) { return mMatchStrategyList.stream().anyMatch(matchStrategy -> matchStrategy.isMatch(states)); } } private interface MatchStrategy { boolean isMatch(Set<Enum<?>> states); } }
当然,你可以用RxJava来实现 :wink: