Android- 创建一个简单的事件订阅组件(一)

本文介绍了一个基于Android平台的简单事件订阅组件实现。通过使用注解和反射技术,实现了跨类别的事件发布与订阅机制。


 Android- 创建一个简单的事件订阅组件(一)

 

  介绍  

          本文将基于反射与注解来介绍如何创建一个简单的事件订阅组件.

    概述

       本文中使用到的注解

           1. @Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明                 的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。

    2. @Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果                         Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。

            3.@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。

      1.既然使用到了注解,那么我们首先创建一个注解类

@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target({ElementType.METHOD}) //只使用在方法上
public @interface Register {

}

2.创建注册与解绑

     //注册
      EventHelper.getInstance().register(this);
     //解绑
      EventHelper.getInstance().unregister(this);

3.既然是事件订阅。那么我们需支持所有的类。包括但不限于(Activity,Fragment,View,自定义类);那么发送的类型为object类型

          
      EventHelper.getInstance().postEvent(new User("你大爷"));



至此 外层调用方法结束。接下来我们实现内部逻辑.

首先开始注册方法register() ,对注册的类必须进行校验来保证事件订阅的成功。如果成功情况下存进map。

public void register(Object object) {
   Class<?> aClass = object.getClass();
 //加入前先校验是否有注解了方法
   checkHasMethod(aClass);
   classHashMap.put(object.hashCode(), object);

   }

   

       该方法对传进来的类进行了方法校验及注解校验.这里的获取方法不推荐getDeclaredMethods(),而是推荐使用公共参数来减少遍历层。




 

/**
     * 校验类方法名
     *
     * @param aClass
     */
    private void checkHasMethod(Class<?> aClass) {
        Method[] methods = aClass.getMethods();
        boolean has_on_event = false;
        int j = 0;
        for (int i = 0; i < methods.length; i++) {
            String name = methods[i].getName();
            Log.i(TAG, "checkHasMethod name:" + name);
            if (name.equals("onEvent")) {
                has_on_event = true;
                j = i;
                break;
            } else {
                has_on_event = false;
            }
        }
        if (!has_on_event) {
            throw new EventException("注册的类里没有onEvent方法或非公共参数");
        }
        Register annotation = methods[j].getAnnotation(Register.class); //检测注解
        if (annotation == null) {
            throw new EventException("注册的onEvent方法未使用Register注解");
        }

    }
对于解绑操作。我们只要将map里对应的实例移除即可;


post方法

   public synchronized void postEvent(Object event) {
        //向所有注册的类发送事件
        for (Map.Entry<Integer, Object> entry : classHashMap.entrySet()) {
            Object value = entry.getValue();
            Class aClass = value.getClass();
            try {
                //
                Method[] methods = aClass.getMethods();
                for (int i = 0; i < methods.length; i++) {
                    Method method = methods[i];
                    if (method.getName().equals("onEvent")) {
                        method.invoke(value, event);
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }



public void unregister(Object object) {
       classHashMap.remove(object.hashCode());
}	


至此整个事件订阅完成,我们来简单的测试一下 MainActivity 创建onEvent方法并使用@Register注解

二级页面也创建一个

发送事件


2个页面成功接收到了参数。

以上只是对注解进行了简单的使用。还能有更复杂的用法及更简便的配置

@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时有效
@Target({ElementType.METHOD}) //只使用在方法上
public @interface Register {
         String value();
}
使用注解来配置所接收的事件;简化流程;

当然以上的简易Demo 对于 多方法还是不支持的。

如何支持,及使用注解来简化流程,下一章节分晓。(待更。)

github源码下载

Android应用中,Flow是一个强大的数据管理库,可以帮助我们实现事件总线的功能。事件总线是种设计模式,用于在应用程序的不同组件之间发布和订阅事件,使得它们能够松耦合地通信。使用Kotlin Flows来构建事件总线可以简化这样的通信,并提供声明式的处理。 以下是使用Kotlin Flows实现事件总线的基本步骤: 1. 创建Event Bus类:首先,创建一个`EventBus`类,它将持有所有Flow的实例,用于存储和广播事件。 ```kotlin class EventBus { private val eventFlows = MutableMap<String, Flow<Event>>() fun publish(event: Event) { eventFlows.values.forEach { flow -> flow.emit(event) } } fun subscribeTo(eventName: String, consumer: (Event) -> Unit): Disposable { val flow = eventFlows.getOrPut(eventName) { createFlowFor(eventName) } return flow.subscribe(consumer) } private suspend fun createFlowFor(eventName: String): Flow<Event> { // 使用Flow.create初始化一个新的无缓冲Flow,后续可以在subscribeTo内部添加过滤、转换等操作 return Flow.create<ChangeEvent> { emitter -> // 添加取消监听的逻辑,如eventBus.dispose() }.onStart { // 在开始时启动事件流,例如从数据库加载初始事件 } } } ``` 2. 发布事件:当一个组件需要发送事件时,调用`EventBus.publish()`并传递事件对象。 3. 订阅事件:其他组件想接收特定事件时,调用`EventBus.subscribeTo(eventName, consumer)`,传入事件名和消费函数。 4. 使用`Disposable`:为了保持良好的内存管理,返回的`Disposable`可以用来取消订阅,避免内存泄漏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值