2 EventBusの原則を反映

ディレクトリ

1)新Librayアンドロイド
2)EventBus反射要素が必要と定義
3)コアクラスはEventBusを実装します

新しいAndroid Libray

ここに画像を挿入説明

EventBus定義された反射要素が必要

。注釈クラスの追加

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;
}

BクラスThreadModeを追加します。

public enum ThreadMode {
   // 事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程,而这个线程可能是UI线程
    POSTING,
    // 事件的处理会在UI线程中执行,事件处理不应太长时间
    MAIN,
    // 后台进程,处理如保存到数据库等操作
    BACKGROUND,
    // 异步执行,另起线程操作。事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作
    ASYNC
}

c。新しいエンティティクラス、メソッドは、サブスクリプションを説明しました

public class MethodManager {

    // 订阅者的回调方法(注解方法)的参数类型
    private Class<?> type;  //定发送进行post时,校验类型

    // 订阅者的回调方法(注解方法)的线程模式
    private ThreadMode threadMode;

    // 订阅者的回调方法(注解方法)
    private Method method;

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

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

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

    public ThreadMode getThreadMode() {
        return threadMode;
    }

    public void setThreadMode(ThreadMode threadMode) {
        this.threadMode = threadMode;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    @NonNull
    @Override
    public String toString() {
        return "MethodManager{" +
                "type=" + type +
                ", threadMode=" + threadMode +
                ", method=" + method +
                '}';
    }
}

EventBusコアクラスを達成


public class EventBus {

    // volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存
    private static volatile EventBus instance;
    // 用来保存这些带注解的方法(订阅者的回调方法)
    private Map<Object, List<MethodManager>> cacheMap;

    private Handler handler;
    private ExecutorService executorService;

    private EventBus() {
        cacheMap = new HashMap<>();

        // Handler高级用法:将handler放在主线程使用
        handler = new Handler(Looper.getMainLooper());
        // 创建一个子线程(缓存线程池)
        executorService = Executors.newCachedThreadPool();
    }

    public static EventBus getDefault() {
        if (instance == null) {
            synchronized (EventBus.class) {
                if (instance == null) {
                    instance = new EventBus();
                }
            }
        }
        return instance;
    }

    // 找到MainActivity所有带符合注解的方法
    public void register(Object getter) {
        // 获取MainActivity所有的方法
        List<MethodManager> methodList = cacheMap.get(getter);
        if (methodList == null) { // 不为空表示以前注册完成
            methodList = findAnnotationMethod(getter);
            cacheMap.put(getter, methodList);
        }
    }

    // 获取MainActivity中所有注解的方法
    private List<MethodManager> findAnnotationMethod(Object getter) {
        List<MethodManager> methodList = new ArrayList<>();
        // 获取类
        Class<?> clazz = getter.getClass();
        // 获取所有方法
        Method[] methods = clazz.getMethods();

        // 性能优化。N个父类不可能有自定义注解。排除后再反射
        while (clazz != null) {
            // 找出系统类,直接跳出,不添加cacheMap(因为不是订阅者)
            String clazzName = clazz.getName();
            if (clazzName.startsWith("java.") || clazzName.startsWith("javax.")
                    || clazzName.startsWith("android.")) {
                break;
            }

            // 循环方法
            for (Method method : methods) {
                // 获取方法的注解
                Subscribe subscribe = method.getAnnotation(Subscribe.class);
                // 判断注解不为空,切记不能抛异常
                if (subscribe == null) {
                    continue;
                }
                // 严格控制方法格式和规范
                // 方法必须是返回void(一次匹配)
                Type returnType = method.getGenericReturnType();
                if (!"void".equals(returnType.toString())) {
                    throw new RuntimeException(method.getName() + "方法返回必须是void");
                }
                // 方法参数必须有值(二次匹配)
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes.length != 1) {
                    throw new RuntimeException(method.getName() + "方法有且只有一个参数");
                }

                // 完全符合要求、规范的方法,保存到方法对象中MethodManager(3个重要成员:方法、参数、线程)
                MethodManager manager = new MethodManager(parameterTypes[0], subscribe.threadMode(), method);
                methodList.add(manager);
            }

            // 不断循环找出父类含有订阅者(注解方法)的类。直到为空,比如AppCompatActivity没有吧
            clazz = clazz.getSuperclass();
        }
        return methodList;
    }

    // SecondActivity发送消息
    public void post(final Object setter) {
        // 订阅者已经登记,从登记表中找出
        Set<Object> set = cacheMap.keySet();
        // 比如获取MainActivity对象
        for (final Object getter : set) {
            // 获取MainActivity中所有注解的方法
            List<MethodManager> methodList = cacheMap.get(getter);
            if (methodList != null) {
                // 循环每个方法
                for (final MethodManager method : methodList) {
                    // 有可能多个方法的参数一样,从而都同时收到发送的消息
                    // 通过EventBean来判断是否匹配上
                    if (method.getType().isAssignableFrom(setter.getClass())) {
                        // 通过方法的类型匹配,从SecondActivity发送的EventBean对象(参数)
                        // 匹配MainActivity中所有注解的方法符合要求的,都发送消息

                        // class1.isAssignableFrom(class2) 判定此 Class 对象所表示的类或接口
                        // 与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口

                        // 线程调度
                        switch (method.getThreadMode()) {
                            case POSTING:
                                invoke(method, getter, setter);
                                break;

                            case MAIN:
                                // 先判断发送方是否在主线程
                                if (Looper.myLooper() == Looper.getMainLooper()) {
                                    invoke(method, getter, setter);
                                } else { // 子线程 - 主线程,切换线程(用到Handler)
                                    handler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            invoke(method, getter, setter);
                                        }
                                    });
                                }
                                break;

                            case BACKGROUND:
                                // 先判断发送方是否在主线程
                                if (Looper.myLooper() == Looper.getMainLooper()) {
                                    // 主线程 - 子线程,创建一个子线程(缓存线程池)
                                    executorService.execute(new Runnable() {
                                        @Override
                                        public void run() {
                                            invoke(method, getter, setter);
                                        }
                                    });
                                } else { // 子线程 到 子线程,不用切换线程
                                    invoke(method, getter, setter);
                                }
                                break;
                        }
                    }
                }
            }
        }
    }

    // 找到匹配方法后,通过反射调用MainActivity中所有符合要求的方法
    private void invoke(MethodManager method, Object getter, Object setter) {
        Method execute = method.getMethod();
        try {
            execute.invoke(getter, setter);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

コードポータル

公開された98元の記事 ウォンの賞賛6 ビュー20000 +

おすすめ

転載: blog.csdn.net/dirksmaller/article/details/104006543