欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EventBus原理解析和手写(一)

程序员文章站 2022-04-02 18:13:18
...

先在android studio添加引用:

implementation 'org.greenrobot:eventbus:3.1.1'

EventBus常规用法:

EventBus原理解析和手写(一)

FirstActivity的xml布局和代码

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="First Activty"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    />

  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="onClick"
    android:text="跳转"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    />

</android.support.constraint.ConstraintLayout>
public class FirstActivity extends AppCompatActivity {
  private static final String TAG = "FirstActivity";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_first);
    EventBus.getDefault().register(this);
  }

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

  @Subscribe(threadMode = ThreadMode.MAIN)
  public void onMessageEvent(MessageEvent event) {
    Log.e(TAG, getClass().getSimpleName() + "接收到的信息是:" + event.getMsg());
  }

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

EventBus原理解析和手写(一)

SecondActivity的xml布局和代码

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Second Activity!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    />
  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="sendMessage"
    android:text="EventBus"
    android:textAllCaps="false"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    />

</android.support.constraint.ConstraintLayout>
public class SecondActivity extends AppCompatActivity {

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

  public void sendMessage(View view) {
    EventBus.getDefault().post(new MessageEvent(getClass().getSimpleName() + "发出消息"));
  }
}

输出结果:

EventBus原理解析和手写(一)

现在我们来尝试编写一下eventbus框架

1、我们先注释掉eventbus引用

EventBus原理解析和手写(一)

同步结果FristActivity和SecondActivity代码如下:

EventBus原理解析和手写(一)

EventBus原理解析和手写(一)

很显然,我们要通过四个类实现EventBus

1、创建线程模式

2、创建注解

3、封装方法类

4、"存储"方法,并通过反射调用

步骤一:先创建EventBus类

很显然,从上面用法看出,EventBus.getDefault()是个单例模式,开始编写EventBus类

public class EventBus {
  private static volatile EventBus instance;

  private EventBus() {

  }

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

创建线程模式:

public enum ThreadMode {
  POSTING,

  MAIN,

  MAIN_ORDERED,

  BACKGROUND,

  ASYNC
}
创建注解类:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
  ThreadMode threadMode() default ThreadMode.MAIN;
}

现在来封装方法EventBus原理解析和手写(一)

public class EventBus {
  private static volatile EventBus instance;

  private EventBus() {

  }

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

  public void register(Object object) {

  }
}

现在我们来理一下思路:因为有可能Activity和Fragment或者说其他类,有可能会有多个接收方法,如

EventBus原理解析和手写(一)

EventBus发出消息,可能也有多个类都接收,所以显然我们需要定义一个map类,来储存哪个类有哪几个方法是需要接收信息

public class EventBus {
  private Map<Object, List<MethodManager>> registerMap;//key用来存储是哪个类,value是该类下的所有接收方法
  private static volatile EventBus instance;

  private EventBus() {
    registerMap = new HashMap<>();
  }

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

  public void register(Object object) {

  }
}
public class MethodManager {
  private Class<?> type;//参数类型
  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;
  }
}

我们再来分析一下,接收的方法注解类一定是我们自定义的,且方法的参数是有且只有一个,返回值为void

public class EventBus {
  private Map<Object, List<MethodManager>> registerMap;//key用来存储是哪个类,value是该类下的所有接收方法
  private static volatile EventBus instance;

  private EventBus() {
    registerMap = new HashMap<>();
  }

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

  public void register(Object object) {
    List<MethodManager> methodList = registerMap.get(object);
    if (methodList == null) {
      methodList = findAnotationMethod(object);
      registerMap.put(object, methodList);
    }

  }

  private List<MethodManager> findAnotationMethod(Object object) {
    List<MethodManager> methodList = new ArrayList<>();
    Class<?> clazz = object.getClass();
    Method[] methods = clazz.getMethods();
    for (Method method : methods) {
      Subscribe subscribe = method.getAnnotation(Subscribe.class);
      if (subscribe == null) {
        continue;
      }
      //特性1:是无返回值的
      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 methodManager = new MethodManager(parameterTypes[0], subscribe.threadMode(), method);
      methodList.add(methodManager);
    }
    return methodList;
  }

  /**
   * 发送消息
   *
   * @param setter 方法参数
   */
  public void post(Object setter) {
    Set<Object> set = registerMap.keySet();
    for (Object key : set) {
      //遍历哪些类中的方法接收的参数类型符合,发送者。
      List<MethodManager> methodList = registerMap.get(key);
      for (MethodManager methodManager : methodList) {
        if (methodManager.getType().isAssignableFrom(setter.getClass())) {
          try {
            methodManager.getMethod().invoke(key, setter);//方法调用
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  /**
   * 接收类
   *
   * @param object 接受者
   */
  public void unregister(Object object) {
    if (registerMap.get(object) != null) {
      registerMap.remove(object);
    }
  }
}

运行结果:

EventBus原理解析和手写(一)