Android EventBus

當咱們進行項目開發的時候,每每是須要應用程序的各組件、組件與後臺線程間進行通訊,好比在子線程中進行請求數據,當數據請求完畢後經過Handler或者是廣播通知UI,而兩個Fragment之家能夠經過Listener進行通訊等等。當咱們的項目愈來愈複雜,使用Intent、Handler、Broadcast進行模塊間通訊、模塊與後臺線程進行通訊時,代碼量大,並且高度耦合。

 

Event 事件。它能夠是任意類型。java

Subscriber 事件訂閱者。在EventBus3.0以前咱們必須定義以onEvent開頭的那幾個方法,分別是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0以後事件處理的方法名能夠隨意取,不過須要加上註解@subscribe(),而且指定線程模型,默認是POSTING。android

Publisher 事件的發佈者。咱們能夠在任意線程裏發佈事件,通常狀況下,使用EventBus.getDefault()就能夠獲得一個EventBus對象,而後再調用post(Object)方法便可。ide


本身從零開始寫EventBus
建立EventBus
/建立Eventbus
    public static EventBus getDefault() {
        if(instance==null)
        {
           synchronized (EventBus.class){
               if (instance==null)
               {

                   instance=new EventBus();
               }
           }
        }
        return instance;
    }

註冊oop

//註冊
    public void register(Object obj) {
       List<SubscribleMethod> list =cachemap.get(obj);
       if(list==null)
       {
         list =findSubscribleMethod(obj);
            cachemap.put(obj,list);

       }
    }

通訊之間的尋找經過註解的方法尋找,這裏爲默認方式post

@Subcrible(threadMode= ThreadMode.MAIN)
、

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subcrible {

ThreadMode threadMode() default ThreadMode.MAIN;

}
 
 
Subcrible的各類狀態
package com.example.eventbus;

import java.lang.reflect.Method;

public class SubscribleMethod {


    //回調方法
    private Method mMethod;
    //線程模式
    private ThreadMode mthreadMode;

    //方法中的參數
    private  Class<?> type;

    public SubscribleMethod(Method mMethod, ThreadMode mthreadMode, Class<?> type) {
        this.mMethod = mMethod;
        this.mthreadMode = mthreadMode;
        this.type = type;
    }

    public void setmMethod(Method mMethod) {
        this.mMethod = mMethod;
    }

    public void setMthreadMode(ThreadMode mthreadMode) {
        this.mthreadMode = mthreadMode;
    }

    public Method getmMethod() {
        return mMethod;
    }

    public ThreadMode getMthreadMode() {
        return mthreadMode;
    }

    public Class<?> getType() {
        return type;
    }

    public void setType(Class<?> type) {
        this.type = type;
    }


}

通訊尋找註解的方法this

  private List<SubscribleMethod> findSubscribleMethod(Object obj) {
         List<SubscribleMethod> list=new ArrayList<>();
         Class< ?> clazz =obj.getClass();
         Method[] methods =clazz.getDeclaredMethods();
         while (clazz!=null)
         {
             //找父類的時候須要先判斷一下是否系統級別的父類
             String name=clazz.getName();
             if(name.startsWith("java.")||name.startsWith("javax.")
           ||name.startsWith("android"))
             {
                 break;
             }
             for (Method method:methods)
             {
                 //找到帶有Subcrible 註解的方法
                 Subcrible subcrible=method.getAnnotation(Subcrible.class);
                 if (subcrible==null)
                 {
                     continue;
                 }
                 //判斷subscrible 註解的方法中的參數類
                 Class<?>[] type=   method.getParameterTypes();
                 if(type.length!=1)
                 {
                     Log.e("TAG", "eventBus only accept one para  " );
                 }
                 ThreadMode threadMode=subcrible.threadMode();
                 SubscribleMethod subscribleMethod=new SubscribleMethod(method,threadMode,type[0]);
                 list.add(subscribleMethod);
             }
                   clazz= clazz.getSuperclass();
         }

        return list;
    }

    public void post(final Object type) {

       //直接循環 Map裏的方法 ,找到相對得而後回調
        Set<Object> set =cachemap.keySet();
        Iterator<Object> iterator=set.iterator();
        while (iterator.hasNext())
        {
            final Object  obj =iterator.next();
            List<SubscribleMethod>list=cachemap.get(obj);
            for (final SubscribleMethod subscribleMethod:list){
                //a(if 條件得對象)對象所對應得類信息是否是b if條件後面得對象對象所對應得接口或者父類
                if (subscribleMethod.getType().isAssignableFrom(type.getClass()))
                {
                    switch (subscribleMethod.getMthreadMode())
                    {
                        case MAIN:
                            //主線程 -主線程
                            if (Looper.myLooper()==Looper.getMainLooper())
                            {
                                invoke(subscribleMethod,obj,type);
                            }
                            else {
                                //子線程 -主線程
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        invoke(subscribleMethod,obj,type);
                                    }
                                });
                            }
                            break;

                    }



                }

            }


        }
    }

    private void invoke(SubscribleMethod subscribleMethod, Object obj, Object type) {
       Method method=subscribleMethod.getmMethod();
     try {
         method.invoke(obj,type);
     }catch (IllegalAccessException e)
     {
         e.printStackTrace();
     }
     catch (InvocationTargetException e)
     {
         e.printStackTrace();
     }


    }
}

運行起來的效果以下spa

 

 

 

 這裏是源碼包分享線程

連接:https://pan.baidu.com/s/1CnTNCndQHizktb4e338BnA
提取碼:vcvx
複製這段內容後打開百度網盤手機App,操做更方便哦code

相關文章
相關標籤/搜索