Android框架解析 - EventBus中的反射
EventBus完成消息的转递,实现过程中使用了大量的反射,我们一起看看反射是怎么使用的
1、使用反射动态创建对象和调用方法
1.1、步骤
1、获取类的Class对象,三种方式
-
通过类名.class获得 Class c1 = User.class;
-
通过对象获得 User user = new User();
Class c1 = user.getClass();
-
forName获得 Class c1 = Class.forName("类的全限定名");
2、通过Class对象无参构造实例化一个对象
3、通过Class对象获取指定方法
4、执行方法,调用Method的invoke方法,参数是(执行方法的对象,执行方法所需的参数值)
1.2、代码
package com.wei.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Test11 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class c1 = Animal.class;
Animal animal = (Animal) c1.newInstance();
Method setName = c1.getDeclaredMethod("setName", String.class);
System.out.println(setName.getModifiers());
System.out.println(Modifier.toString(setName.getModifiers()));
setName.invoke(animal,"猫咪");
System.out.println(animal);
}
}
class Animal{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Animal(String name) {
this.name = name;
}
public Animal() {
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
'}';
}
}
2、Event的执行流程
2.1、register方法
register方法的参数是Activity或者Fragment,以Activity为例。通过反射遍历所有Activity中所有的方法,筛选出以onEvent开头并方法,封装成new SubscriberMethod(method, threadMode, eventType) 对象,多个对象存在list,也就是subscriberMethods 对象中
遍历subscriberMethods ,按照eventType(也就是自定义的Event类,作为参数传入onEventXX方法中)进行分组,每个eventType对应一个subscriptions对象-由new Subscription(Activity,method,priority) 组成的List。
2.2、post方法
1、post方法的参数是一个eventType,根据这个eventType,找到对应的subscriptions对象,然后根据对象中的Activity和method就可以直接invoke调用,代码如下:
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
2、考虑threadMode的情况下:
PostThread:在post方法调用的线程进行invoke
MainThread:首先去判断当前如果是UI线程,则直接调用;否则: mainThreadPoster.enqueue(subscription, event);把当前的方法加入到队列,然后直接通过handler去发送一个消息,在handler的handleMessage中,去执行我们的方法。说白了就是通过Handler去发送消息,然后执行的
BackgroundThread:如果当前非UI线程,则直接调用;如果是UI线程,则将任务加入到后台的一个队列,最终由Eventbus中的一个线程池去调用
executorService = Executors.newCachedThreadPool();
Async:将任务加入到后台的一个队列,最终由Eventbus中的一个线程池去调用;线程池与BackgroundThread用的是同一个
这么说BackgroundThread和Async有什么区别呢?
3、BackgroundThread中的任务,一个接着一个去调用,中间使用了一个布尔型变量handlerActive进行的控制。
Async则会动态控制并发。
2.3、相关博客
Android EventBus源码解析 带你深入理解EventBus
|