Android eventbus open-source framework (imitation)
SubscriberMethodFinder finds the SubscriberMethod class SubscriberMethod method registration method combination subscriber user and method key value corresponding class AsyncPoster asynchronous initiation class HandlerPoster main thread initiation class PostBeen message class (the initiating class executes callback based on the message) eventBus classification class (builder Mode)
**
Note !!!!! Enabling new threads in the onCreate method is generally the primary thread by default, and can be initiated only when the primary thread is idle. Looper. myQueue (). addIdleHandler
**
MainActivity
package com.lvshujun.customeventbus;import com.lvshujun.event.EventBus;import android.app.Activity;import android.os.Bundle;import android.os.Looper;import android.os.MessageQueue.IdleHandler;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this); //EventBus.getDefault().unregister(this); Looper.myQueue().addIdleHandler(new IdleHandler() { @Override public boolean queueIdle() { // TODO Auto-generated method stub EventBus.getDefault().post(new ResponseEvent()); return false; } }); } public void onEventMainThread(ResponseEvent event) { System.out.println(Thread.currentThread().getName()); }}
SubscriberMethodFinder
package com.lvshujun.event;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class SubscriberMethodFinder { private static final Map
> methodCache = new HashMap
>(); List
findSubscriberMethods(Class
subscriberClass) { String cName = subscriberClass.getName(); List
subscriberMethods = null; synchronized (methodCache) { subscriberMethods = methodCache.get(cName); } if(subscriberMethods != null) return subscriberMethods; subscriberMethods = new ArrayList
(); if(subscriberClass != null) { Method[] methods = subscriberClass.getDeclaredMethods(); for(Method method:methods) { String methodName = method.getName(); if(methodName.startsWith(onEvent)) { Class
[] parameterTypes = method.getParameterTypes(); if(parameterTypes.length == 1) { SubscriberMethod sm = new SubscriberMethod(method, parameterTypes[0]); subscriberMethods.add(sm); } } } } methodCache.put(cName, subscriberMethods); return subscriberMethods; }}
Subtasks
package com.lvshujun.event;public final class Subscription { public final Object subscriber; public final SubscriberMethod subscriberMethod; Subscription(Object subscriber, SubscriberMethod subscriberMethod) { this.subscriber = subscriber; this.subscriberMethod = subscriberMethod; }}
SubscriberMethod
package com.lvshujun.event;import java.lang.reflect.Method;public final class SubscriberMethod { final public Method method; final public Class
eventType; SubscriberMethod(Method method, Class
eventType) { this.method = method; this.eventType = eventType; }}
HandlerPoster
package com.lvshujun.event;import java.util.LinkedList;import java.util.Queue;import android.os.Handler;import android.os.Looper;import android.os.Message;final class HandlerPoster extends Handler { private Queue
queue; private final EventBus eventBus; HandlerPoster(EventBus eventBus, Looper looper) { super(looper); this.eventBus = eventBus; queue = new LinkedList
(); } @Override public void handleMessage(Message msg) { try { PostBeen pendingPost = queue.poll(); if (pendingPost == null) { } else { eventBus.invokeSubscriber(pendingPost); } } catch (Exception e) { } finally { } } void enqueue(Subscription subscription, Object event) { queue.add(new PostBeen(event, subscription)); sendMessage(obtainMessage()); }}
AsyncPoster
package com.lvshujun.event;import java.util.LinkedList;import java.util.Queue;public class AsyncPoster implements Runnable { private Queue
queue; private EventBus eventBus; public AsyncPoster(EventBus eventBus) { // super(looper); this.eventBus = eventBus; queue = new LinkedList
(); } @Override public void run() { // TODO Auto-generated method stub try { PostBeen pendingPost = queue.poll(); if (pendingPost == null) { } else { eventBus.invokeSubscriber(pendingPost); } } catch (Exception e) { } finally { } } void enqueue(Subscription subscription, Object event) { queue.add(new PostBeen(event, subscription)); eventBus.executorService.execute(this); }}
PostBeen
package com.lvshujun.event;public class PostBeen { public Object event; public Subscription subscription; public PostBeen(Object obj,Subscription sub) { this.event = obj; this.subscription = sub; }}
EventBus
package com.lvshujun.event;import java.lang.reflect.InvocationTargetException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.os.Looper;public class EventBus { private SubscriberMethodFinder methodFinder; ExecutorService executorService = Executors.newCachedThreadPool(); private HandlerPoster handlerPoster; private AsyncPoster asyncPoster; private final Map
, CopyOnWriteArrayList
> subscriptionsByEventType; private final Map
>> typesBySubscriber; public static EventBus single; public static EventBus getDefault() { if (single == null) { synchronized (EventBus.class) { if (single == null) { single = new EventBus(); } } } return single; } public synchronized void register(Object subscriber) { List
subscriberMethods = methodFinder.findSubscriberMethods(subscriber.getClass()); for (SubscriberMethod method : subscriberMethods) { Class
eventType = method.eventType; CopyOnWriteArrayList
subscriptions = subscriptionsByEventType.get(eventType); Subscription newSubscription = new Subscription(subscriber, method); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList
(); subscriptionsByEventType.put(eventType, subscriptions); } subscriptions.add(newSubscription); List
> subscribedEvents = typesBySubscriber.get(subscriber); if (subscribedEvents == null) { subscribedEvents = new ArrayList
>(); typesBySubscriber.put(subscriber, subscribedEvents); } subscribedEvents.add(eventType); } } public synchronized void unregister(Object subscriber) { List
> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class
eventType : subscribedTypes) { List
subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions != null) { int size = subscriptions.size(); for (int i = 0; i < size; i++) { Subscription subscription = subscriptions.get(i); if (subscription.subscriber == subscriber) { System.out.println(subscription.subscriberMethod.method.getName()); subscriptions.remove(i); i--; size--; } } } } typesBySubscriber.remove(subscriber); } } public EventBus() { methodFinder = new SubscriberMethodFinder(); subscriptionsByEventType = new HashMap
, CopyOnWriteArrayList
>(); typesBySubscriber = new HashMap
>>(); handlerPoster = new HandlerPoster(this, Looper.getMainLooper()); asyncPoster = new AsyncPoster(this); } public void post(Object obj) { List
subscriptions = subscriptionsByEventType.get(obj.getClass()); if (subscriptions != null) { for (Subscription subscription : subscriptions) { System.out.println(subscription.subscriberMethod.method.getName()); //handlerPoster.enqueue(subscription, obj); asyncPoster.enqueue(subscription, obj); } } } public void invokeSubscriber(PostBeen been) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { Subscription sub = been.subscription; sub.subscriberMethod.method.invoke(sub.subscriber, been.event); }}