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来实现 😉