手写EventBus框架

手写EventBus框架

EventBus相信大家都用过,EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。

今天我们就来手写EventBus,让我们更了解EventBus原理。

需要了解的知识点:
1.反射
2.注解

下面我们就来开始:

先来看下注解,

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscriber {
    ThreadMode value() default  ThreadMode.PostThread;
}

再来看下线程枚举:

public enum ThreadMode {

/**
 * Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery
 * implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
 * simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers
 * using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
 */
PostThread,

/**
 * Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is
 * the main thread, event handler methods will be called directly. Event handlers using this mode must return
 * quickly to avoid blocking the main thread.
 */
MainThread,

/**
 * Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods
 * will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
 * background thread, that will deliver all its events sequentially. Event handlers using this mode should try to
 * return quickly to avoid blocking the background thread.
 */
BackgroundThread,

/**
 * Event handler methods are called in a separate thread. This is always independent from the posting thread and the
 * main thread. Posting events never wait for event handler methods using this mode. Event handler methods should
 * use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
 * of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus
 * uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
 */
Async

}

再来看下保存注册类中带Subscriber注解的类SubscriberMethod:

//运行方法
private Method method;
//指定运行线程
private ThreadMode threadMode;
 //方法参数类型
private Class<?> eventType;


public SubscriberMethod(Method method, ThreadMode threadMode, Class<?> eventType) {
    this.method = method;
    this.threadMode = threadMode;
    this.eventType = eventType;
}

最后我们来看下核心的类EventBus:

public class EventBus {

    //单例
    private static volatile EventBus defaultInstance;
    //保存带有Subscriber注解的方法
    private Map<Object,CopyOnWriteArrayList<SubscriberMethod>> map = new HashMap<>();

    //主线程
    private Handler mHadnler=null;
    //线程池
    private ExecutorService executorService=null;


    private EventBus(){
        mHadnler=new Handler(Looper.getMainLooper());
        executorService = Executors.newCachedThreadPool();
    }

    /**
     * 单例
     * @return
     */
    public static EventBus getDefault(){
        if(defaultInstance == null){
            synchronized (EventBus.class){
                if(defaultInstance == null){
                    defaultInstance = new EventBus();
                }
            }
        }
        return defaultInstance;
    }


    /**
     * 注册
     * @param activity
     */
    public void register(Object activity){
        CopyOnWriteArrayList<SubscriberMethod> list = map.get(activity);
        if(list == null){
            list=obtainSubscriberMethods(activity);
            map.put(activity,list);
        }

    }

    /**
     * 注销
     * @param activity
     */
    public void  unregister(Object activity){
        map.remove(activity);
    }

    /**
     * 发布
     * @param event
     */
    public void post(final Object event){
        Set<Map.Entry<Object, CopyOnWriteArrayList<SubscriberMethod>>> entries = map.entrySet();

        for (Map.Entry<Object, CopyOnWriteArrayList<SubscriberMethod>> entry : entries) {
            final Object object = entry.getKey();
            CopyOnWriteArrayList<SubscriberMethod> list = entry.getValue();
            for (SubscriberMethod subscriberMethod : list) {
                if(subscriberMethod.getEventType().isAssignableFrom(event.getClass())){
                    final Method method = subscriberMethod.getMethod();

                    switch (subscriberMethod.getThreadMode()){
                        case PostThread:
                            invoke(object,method,event);

                            break;
                        case MainThread:
                            if(Looper.myLooper() == Looper.getMainLooper()){
                                invoke(object,method,event);
                            }else {
                                mHadnler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(object,method,event);
                                    }
                                });
                            }
                            break;
                        case BackgroundThread:
                        case Async:
                            if(Looper.myLooper() == Looper.getMainLooper()){
                                executorService.execute(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(object,method,event);
                                    }
                                });
                            }else {
                                invoke(object,method,event);
                            }
                        default:
                            break;
                    }
                }

            }

        }
    }

    /**
     * 调用方法
     * @param object
     * @param method
     * @param event
     */
    private void invoke(Object object,Method method,Object event){
        try {
            if(!method.isAccessible()){
                method.setAccessible(true);
            }
            method.invoke(object,event);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取注册类中的方法
     * @param activity
     * @return
     */
    private CopyOnWriteArrayList<SubscriberMethod> obtainSubscriberMethods(Object activity) {

        CopyOnWriteArrayList<SubscriberMethod> list=new CopyOnWriteArrayList<>();
       Class<?> clazz = activity.getClass();
       while(clazz != null){

            String clazzName = clazz.getName();
            if(clazzName.startsWith("android.") || clazzName.startsWith("java.")
                    || clazzName.startsWith("javax.") || clazzName.startsWith("org.")){
                break;
            }

            Method[] methods =
                    clazz.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                Subscriber annotation = method.getAnnotation(Subscriber.class);
                if(annotation == null){
                    continue;
                }
                Class<?>[] parameterTypes = method.getParameterTypes();
                if(parameterTypes == null || parameterTypes.length!=1){
                    throw new RuntimeException("eventbus method params size must be one!");
                }

                ThreadMode threadMode = annotation.value();
                Class<?> parameterType = parameterTypes[0];

                SubscriberMethod subscriberMethod = new SubscriberMethod(method,threadMode,parameterType);

                list.add(subscriberMethod);
            }

            clazz = clazz.getSuperclass();
        }


        return list;
    }
}

我们在来看下使用:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    EventBus.getDefault().register(this);
}

public void jump(View view){
    startActivity(new Intent(this,SecondActivity.class));
}

@Subscriber(ThreadMode.PostThread)
public void receive(TestBean bean){
    Log.e("MainActivity","thread===>"+Thread.currentThread().getName() +"===>"+bean);

}

@Override
protected void onDestroy() {
    EventBus.getDefault().unregister(this);
    super.onDestroy();
}





 EventBus.getDefault().post(new TestBean("发送的消息"));

下载地址:EventBus-Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值