import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;
/**
* Publish/Subscribe
*/
public class EventBus {
private static final String TAG = "EventBus";
/**
* 子线程
*/
public static final int THREAD_SUB = 0;
/**
* 当前线程
*/
public static final int THREAD_CURRENT = 1;
/**
* 主线程
*/
public static final int THREAD_MAIN = 2;
private static final int EXECUTOR_POOL_SIZE = 1;
private static final HashMap<String, EventBus> BUS = new HashMap<String, EventBus>();
private static final ReentrantLock lock = new ReentrantLock();
private static ExecutorService EXECUTOR = null;
/**
* 事件回调
*/
public interface ICallback {
void onEvent(Event event);
}
/**
* 事件
*/
public static class Event {
private String action;
private Bundle bundle;
public Event(String action) {
this.action = action;
bundle = new Bundle();
}
public String getAction() {
return action;
}
public Bundle getBundle() {
return bundle;
}
}
private ArrayList<CallbackHandler> handlers = new ArrayList<CallbackHandler>();
private EventBus() {
}
/**
* 发布
*
* @param event
*/
public static void publish(Event event) {
if(null == event){
return;
}
String action = event.action;
if (action == null) {
return;
}
lock.lock();
try {
EventBus bus = BUS.get(action);
if (bus != null) {
ArrayList<CallbackHandler> handlers = bus.handlers;
for (CallbackHandler handler : handlers) {
handler.post(event);
}
}
} finally {
lock.unlock();
}
}
/**
* 订阅
*
* @param callback 接收到事件后执行的回调
* @param thread 执行回调所在的线程,取值为THREAD_SUB、THREAD_CURRENT、THREAD_MAIN
* @param actions 订阅的事件类型
*/
public static void subscribe(ICallback callback, int thread, String... actions) {
if (callback == null || actions == null || actions.length == 0) {
return;
}
lock.lock();
try {
CallbackHandler handlerToAdd = null;
for (String action : actions) {
if (action == null) {
continue;
}
EventBus bus = BUS.get(action);
if (bus == null) {
bus = new EventBus();
BUS.put(action, bus);
}
ArrayList<CallbackHandler> handlers = bus.handlers;
boolean added = false;
for (CallbackHandler handler : handlers) {
if (handler.callback == callback) {
added = true;
break;
}
}
if (!added) {
if (handlerToAdd == null) {
handlerToAdd = new CallbackHandler(callback, thread);
}
handlers.add(handlerToAdd);
}
}
} finally {
lock.unlock();
}
}
/**
* 取消订阅
*
* @param callback
* @param actions 取消订阅的事件类型
*/
public static void unsubscribe(ICallback callback, String... actions) {
if (callback == null || actions == null || actions.length == 0) {
return;
}
lock.lock();
try {
for (String action : actions) {
if (action == null) {
continue;
}
EventBus bus = BUS.get(action);
if (bus == null) {
continue;
}
ArrayList<CallbackHandler> handlers = bus.handlers;
int index = 0;
int size = handlers.size();
for (; index < size; index++) {
if (handlers.get(index).callback == callback) {
break;
}
}
if (index < size) {
handlers.remove(index);
if (handlers.isEmpty()) {
BUS.remove(action);
if (BUS.isEmpty() && EXECUTOR != null) {
EXECUTOR.shutdown();
EXECUTOR = null;
}
}
}
}
} finally {
lock.unlock();
}
}
private static class CallbackHandler {
ICallback callback;
Handler handler;
CallbackHandler(ICallback callback, int thread) {
this.callback = callback;
if (thread == THREAD_CURRENT) {
Looper looper = Looper.myLooper();
if (looper == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
handler = new Handler(looper);
} else if (thread == THREAD_MAIN) {
handler = new Handler(Looper.getMainLooper());
} else {
// 默认使用子线程
handler = null;
}
}
void post(final Event event) {
Runnable runable = new Runnable() {
@Override
public void run() {
long t0 = System.currentTimeMillis();
try {
callback.onEvent(event);
} finally {
// 如果子线程中的回调执行时间太长,给出提示
if (handler == null) {
long t = System.currentTimeMillis() - t0;
if (t > 5 * 1000) {
LogUtil.d(true,TAG, callback.getClass().getName(), " takes too long (", t, "ms)!");
}
}
}
}
};
if (handler != null) {
handler.post(runable);
} else {
if (EXECUTOR == null) {
EXECUTOR = Executors.newFixedThreadPool(EXECUTOR_POOL_SIZE);
}
EXECUTOR.execute(runable);
}
}
}
}