前言
EventBus系列文章
EventBus系列文章(一) - register()、subscribe()、post()分析
EventBus系列文章(二) - 手写EventBus
1. 手写EventBus
从MainActivity跳转TestActivity,然后点击TestActivity,把数据会传到MainActivity即可;
2. 代码如下
1>:MainActivity代码如下:
/**
* Email: [email protected]
* Created by Novate 2018/6/16 8:42
* Version 1.0
* Params:
* Description:
*/
public class MainActivity extends AppCompatActivity {
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册,思考为什么要注册?
EventBus.getDefault().register(this);
// 进入测试界面
mTv = (TextView) findViewById(R.id.test_tv);
mTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,TestActivity.class);
startActivity(intent);
}
});
}
/**
* threadMode 执行的线程方式
* priority 执行的优先级
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 50,sticky = true)
public void test1(String msg){
// 如果有一个地方用 EventBus 发送一个 String 对象,那么这个方法就会被执行
Log.e("TAG","msg1 = "+msg);
mTv.setText(msg);
}
/**
* threadMode 执行的线程方式
* priority 执行的优先级,值越大优先级越高
* sticky 粘性事件
*/
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100,sticky = true)
public void test2(String msg){
// 如果有一个地方用 EventBus 发送一个 String 对象,那么这个方法就会被执行
Log.e("TAG","msg2 = "+msg);
mTv.setText(msg);
}
@Override
protected void onDestroy() {
// 解绑,思考为什么要解绑?
EventBus.getDefault().unregister(this);
super.onDestroy();
}
}
2>:TestActivity代码如下:
/**
* Email: [email protected]
* Created by Novate 2018/6/16 8:42
* Version 1.0
* Params:
* Description:
*/
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post("text");
}
});
}
}
3>:EventBus代码如下
/**
* Email: [email protected]
* Created by Novate 2018/6/10 11:08
* Version 1.0
* Params:
* Description:
*/
public class EventBus {
// subscriptionsByEventType 这个集合存放的是?
// key 是 Event 参数的类
// value 存放的是 Subscription 的集合列表
// Subscription 包含两个属性,一个是 subscriber 订阅者(反射执行对象),一个是 SubscriberMethod 注解方法的所有属性参数值
private final Map, CopyOnWriteArrayList> subscriptionsByEventType;
// typesBySubscriber 这个集合存放的是?
// key 是所有的订阅者
// value 是所有订阅者里面方法的参数的class
private final Map
4>:AsyncPoster代码如下:
/**
* Posts events in background.
*
* @author Markus
*/
class AsyncPoster implements Runnable {
Subscription subscription;
Object event;
// 线程池
private final static ExecutorService executorService = Executors.newCachedThreadPool();
public AsyncPoster(Subscription subscription, Object event){
this.subscription = subscription;
this.event = event;
}
public static void enqueue(Subscription subscription, Object event) {
AsyncPoster asyncPoster = new AsyncPoster(subscription,event);
// 用线程池
executorService.execute(asyncPoster);
}
@Override
public void run() {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber,event);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
5>:Subscribe注解代码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
}
>6:SubscriberMethod代码如下:
/** Used internally by EventBus and generated subscriber indexes. */
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class eventType;
final int priority;
final boolean sticky;
/** Used for efficient comparison */
String methodString;
public SubscriberMethod(Method method, Class eventType, ThreadMode threadMode, int priority, boolean sticky) {
this.method = method;
this.threadMode = threadMode;
this.eventType = eventType;
this.priority = priority;
this.sticky = sticky;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else if (other instanceof SubscriberMethod) {
checkMethodString();
SubscriberMethod otherSubscriberMethod = (SubscriberMethod)other;
otherSubscriberMethod.checkMethodString();
// Don't use method.equals because of http://code.google.com/p/android/issues/detail?id=7811#c6
return methodString.equals(otherSubscriberMethod.methodString);
} else {
return false;
}
}
private synchronized void checkMethodString() {
if (methodString == null) {
// Method.toString has more overhead, just take relevant parts of the method
StringBuilder builder = new StringBuilder(64);
builder.append(method.getDeclaringClass().getName());
builder.append('#').append(method.getName());
builder.append('(').append(eventType.getName());
methodString = builder.toString();
}
}
@Override
public int hashCode() {
return method.hashCode();
}
}
7>:Subscription注解代码如下:
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
/**
* Becomes false as soon as {@link EventBus#unregister(Object)} is called, which is checked by queued event delivery
* {@link EventBus#invokeSubscriber(PendingPost)} to prevent race conditions.
*/
volatile boolean active;
Subscription(Object subscriber, SubscriberMethod subscriberMethod) {
this.subscriber = subscriber;
this.subscriberMethod = subscriberMethod;
active = true;
}
@Override
public boolean equals(Object other) {
if (other instanceof Subscription) {
Subscription otherSubscription = (Subscription) other;
return subscriber == otherSubscription.subscriber
&& subscriberMethod.equals(otherSubscription.subscriberMethod);
} else {
return false;
}
}
@Override
public int hashCode() {
return subscriber.hashCode() + subscriberMethod.methodString.hashCode();
}
}
8>:ThreadMode代码如下:
/**
* Each event handler method has a thread mode, which determines in which thread the method is to be called by EventBus.
* EventBus takes care of threading independently from the posting thread.
*
* @see EventBus#register(Object)
* @author Markus
*/
public enum ThreadMode {
/**
* Subscriber will be called in the same thread, which is posting the event. This is the default. Event delivery
* implies the least overhead because it avoids thread switching completely. Thus this is the recommended mode for
* simple tasks that are known to complete is a very short time without requiring the main thread. Event handlers
* using this mode must return quickly to avoid blocking the posting thread, which may be the main thread.
*/
/**
* 同一个线程,在哪个线程发送事件,那么该方法就在哪个线程执行
*/
POSTING,
/**
* Subscriber will be called in Android's main thread (sometimes referred to as UI thread). If the posting thread is
* the main thread, event handler methods will be called directly. Event handlers using this mode must return
* quickly to avoid blocking the main thread.
*/
/**
* 在主线程中执行
*/
MAIN,
/**
* Subscriber will be called in a background thread. If posting thread is not the main thread, event handler methods
* will be called directly in the posting thread. If the posting thread is the main thread, EventBus uses a single
* background thread, that will deliver all its events sequentially. Event handlers using this mode should try to
* return quickly to avoid blocking the background thread.
*/
/**
* 子线程:如果发布事件的线程是主线程,那么调用线程池中的子线程来执行订阅方法;否则直接执行;
*/
BACKGROUND,
/**
* Event handler methods are called in a separate thread. This is always independent from the posting thread and the
* main thread. Posting events never wait for event handler methods using this mode. Event handler methods should
* use this mode if their execution might take some time, e.g. for network access. Avoid triggering a large number
* of long running asynchronous handler methods at the same time to limit the number of concurrent threads. EventBus
* uses a thread pool to efficiently reuse threads from completed asynchronous event handler notifications.
*/
/**
* 异步线程:无论发布事件执行在主线程还是子线程,都利用一个异步线程来执行订阅方法。
*/
ASYNC
}
代码已上传至github:
https://github.com/shuai999/Architect_day22.git