m0_ sixty-four million three hundred and eighty-three thousand 2022-01-26 15:20:14 阅读数:756
EventBus So many years since its birth , It can be seen in many production projects . As you can see from the update log , Except for the small size , It's stable , It hasn't been updated in the past two years , The last update is just because it supports all JVM, Let it be used in more than Android On .
It's very stable , Stable enough to give a feeling , If you use EventBus What's the problem , That must be the wrong way you used it .
EventBus How to use , about Android The old driver said , It must be familiar , There's too much information , I won't go into that here .
stay Android Next , Thread switching is a very common and necessary operation ,EventBus In addition to being able to subscribe and send messages , It can also specify the thread that receives the message processing message .
in other words , No matter what you do post()
What thread is the message in ,EventBus You can distribute messages to the thread you specify , It sounds very convenient .
But no matter how you switch , There are only a few cases :
UI Thread cutting sub thread .
Sub thread cutting UI Threads .
Sub thread cutting other sub threads .
When we use EventBus When registering a message , Can pass @Subscribe
Annotation to complete the registration event , @Subscribe
You can use the parameter threadMode
To specify which thread to use to receive messages .
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventTest(event:TestEvent){
// Handling events
}
threadMode
It's a enum, There are many modes to choose from :
POSTING, The default value is , That thread sends is that thread receives .
MAIN, Switch to the main thread to receive events .
MAIN_ORDERED,v3.1.1 New properties in , Also switch to the main thread to receive events , But and MAIN There are some differences , I'll tell you more later .
BACKGROUND, Make sure to receive events... In the child thread . The details are , If it's a message sent by the main thread , Will switch to the sub thread receive , And if the event itself is emitted by a child thread , The thread that sends the event message will be used directly to process the message .
ASYNC, Make sure to receive events... In the child thread , But and BACKGROUND The difference is that , It does not distinguish whether the sending thread is a child thread , It's receiving events in different threads every time .
EventBus Thread switch of , The main method involved is EventBus Of postToSubscription()
Method .
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch (subscription.subscriberMethod.threadMode) {
case POSTING:
invokeSubscriber(subscription, event);
break;
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
if (mainThreadPoster != null) {
mainThreadPoster.enqueue(subscription, event);
} else {
// temporary: technically not correct as poster not decoupled from subscriber
invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
case ASYNC:
asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
You can see , stay postToSubscription()
In the method , For our configuration threadMode Value is processed .
This code logic is very simple , Let's take a look at the details of their implementation .
Want to receive messages in the main thread , Need configuration threadMode by MAIN.
case MAIN:
if (isMainThread) {
invokeSubscriber(subscription, event);
} else {
mainThreadPoster.enqueue(subscription, event);
}
The logic of this passage is very clear , It is judged that the main thread will directly handle the event , If it's a non main thread , Just use mainThreadPoster Handling events .
track mainThreadPoster
Code for , The concrete logic code is in HandlerPoster Class , It has achieved Poster Interface , This is a common Handler, It's just its Looper Using the main thread 「Main Looper」, Messages can be distributed to the main thread .
In order to improve efficiency ,EventBus There are also some minor optimizations here , It's worth learning from .
In order to avoid frequent to main thread sendMessage()
,EventBus The way to do this is to process as many message events as possible in one message , So we used while loop , Continue from message queue queue Get message from .
At the same time, in order to avoid occupying the main thread for a long time , interval 10ms (maxMillisInsideHandleMessage = 10ms) Will resend sendMessage()
, Used to relinquish the execution rights of the main thread , Avoid creating UI Carton and ANR.
MAIN
It can ensure the reception of events , In the main thread , It should be noted that , If the event is sent in the main thread , Then use MAIN
Will directly execute . In order to make the development and configurable Chengdu higher , stay EventBus v3.1.1 Added MAIN_ORDERED
, It doesn't differentiate between the current thread , It's all about using mainThreadPoster
To deal with it , That is to say, I will walk once Handler The distribution of messages .
When events need to be processed in the main thread , Time consuming operations are not required , There's nothing to say , In addition to MAIN
perhaps MAIN_ORDERED
The choice of , It depends on the specific business requirements .
Want messages to be processed in child threads , You can configure the threadMode by BACKGROUND
perhaps AYSNC
, They can all achieve , But there are some differences .
First look at it. BACKGROUND
, adopt postToSubscription()
The logic in can be seen in ,BACKGROUND
The thread that will distinguish the current event , Is it the main thread , This is not the main thread that distributes events directly , If it's the main thread , be backgroundPoster
To distribute Events .
case BACKGROUND:
if (isMainThread) {
backgroundPoster.enqueue(subscription, event);
} else {
invokeSubscriber(subscription, event);
}
break;
BackgroundPoster It has also been realized. P
《 A big factory Java Analysis of interview questions + Back end development learning notes + The latest architecture explanation video + Practical project source code handout 》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 Full content open source sharing
oster Interface , It also maintains a message queue implemented by linked list PendingPostQueue,
In some It's mentioned in the coding specification , Don't create threads directly , Instead, you need to use a thread pool .EventBus And follow the rules , stay BackgroundPoster in , I used EventBus Of executorService
Thread pool object to execute .
In order to improve efficiency ,EventBus Processing BackgroundPoster when , There are also some tips worth learning .
You can see , stay BackgroundPoster in , When processing events thrown by the main thread , There will only be one thread at a time , To loop from the queue , Get event handling event .
adopt synchronized Synchronization lock to ensure the thread safety of queue data , Simultaneous utilization volatile Identification of the executorRunning
To ensure that the execution state seen under different threads is visible .
since BACKGROUND
When dealing with tasks , Only one thread will be used , however EventBus But it uses thread pool , It seems a little wasteful . But learn more about ASYNC
The implementation of the , Just know how to make full use of thread pool .
And what I mentioned earlier threadMode equally , Most of them correspond to one Poster, and ASYNC
Corresponding Poster yes AsyncPoster, There was no special treatment , All events , They are all brainless EventBus Of executorService
This thread pool , This guarantees , Whatever the thread of the event , And the thread that receives the event , It must be different , It also guarantees that the event will be processed in the sub thread .
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
queue.enqueue(pendingPost);
copyright:author[m0_ sixty-four million three hundred and eighty-three thousand ],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/01/202201261520121994.html