EventBusソース分析続編
11267 ワード
上記の送信方法では3つのpostイベントが使用されています.次に、これらのpostイベントを分析します.メインスレッドのスケジューリング: MainThreadSupport:
上記の方法から、最終的に作成されたposterはHandlerPosterであることがわかる. HandlerPoster
HandlerPosterは、実はHandlerの実装であり、内部でPendingPostQueueのメッセージキューを維持し、enqueue(Subscription subscription,Object event)メソッドでpendingPostPoolのArrayListキャッシュプールからPendingPostをPendingPostに追加し、そのPendingPostQueueイベントをHandlerに送信して処理する.
handleMessageでは、1つのwhileデッドサイクルにより、PendingPostQueueからPendingPostを取り出して実行し続け、postを取得した後、eventBusがそのpostを通じて対応するSubscriber処理イベントを検索する. whileが脱退する条件は2つある.取得されたPendingPostはnullであり、PendingPostQueueには処理可能なメッセージがありません.2.各PendingPostがHandlerで実行される時間が最大実行時間を超えている. 2.BackgroundPoster
BackgroundPosterが実現したのはRunnableで、私たちはそのrun方法を見て、PendingPostQueueからpendingPostをEventBusに取り出して配布し続け、ここで外部がwhile()死循環であることに注意して、PendingPostQueueの中のすべてのpendingPostが配布されることを意味します.なぜなら、BackGroundThreadバックグラウンドスレッドは、これが唯一なので、このスレッドに送信されたイベントはキューに配置され、購読時にループしてすべて送信される必要があります. 3.AsyncPosterというposterもBackgroundPosterも実装されているRunnableですが、彼らのrun方法は実装が異なり、1つの配布を取り出すだけです.理由:ASYNC:このスレッドは、パブリッシュイベントがどのスレッドにあるかにかかわらず、サブスクリプション時に空のスレッドになるため、スレッドは互いに独立してカートンは現れません.
3つのposterで使用されるキューPendingPostQueue: PendingPost:
5.ログアウト unregisterメソッド:
登録プロセスでは、typesBySubscriberがサブスクライバのすべてのサブスクライバイベントタイプを保存するMapであることがわかります.ここでは、サブスクライバに基づいてサブスクライバイベントタイプリストを取得し、1つずつサブスクライバをキャンセルし、最後にtypesBySubscriberがサブスクライバを削除します. unsubscribeByEventTypeメソッド:
subscriptionsByEventTypeはイベントタイプ対応サブスクリプション情報を格納するMapであり、コードロジックが非常に明確で、あるイベントタイプのサブスクリプション情報リストを探し出し、サブスクリプション情報を遍歴し、サブスクリプションをキャンセルするサブスクライバとサブスクリプション情報をカプセル化するサブスクライバとを対比し、同一であれば、そのサブスクリプション情報が失効することを説明し、そのサブスクリプション情報を除去する.
/**
* Interface to the "main" thread, which can be whatever you like. Typically on Android, Android's main thread is used.
* “ ” , 。 Android Android 。
*/
public interface MainThreadSupport {
boolean isMainThread();
Poster createPoster(EventBus eventBus);
class AndroidHandlerMainThreadSupport implements MainThreadSupport {
private final Looper looper;
public AndroidHandlerMainThreadSupport(Looper looper) {
this.looper = looper;
}
@Override
public boolean isMainThread() {
return looper == Looper.myLooper();
}
@Override
public Poster createPoster(EventBus eventBus) {
return new HandlerPoster(eventBus, looper, 10);
}
}
}
上記の方法から、最終的に作成されたposterはHandlerPosterであることがわかる.
public class HandlerPoster extends Handler implements Poster {
private final PendingPostQueue queue; // Post Events
private final int maxMillisInsideHandleMessage; // post handlerMessage ,
private final EventBus eventBus;
private boolean handlerActive; // handler
protected HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
super(looper);
this.eventBus = eventBus;
this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
// pendingPostPool ArrayList PendingPost PendingPostQueue , PendingPost Handler
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
queue.enqueue(pendingPost); // pendingPost
if (!handlerActive) { // Handler
handlerActive = true;
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
@Override
public void handleMessage(Message msg) {
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
while (true) { // , PendingPost post
PendingPost pendingPost = queue.poll();
if (pendingPost == null) { // null, post , Handler , while
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false; // Handler
return;
}
}
}
// post eventBus post Subscriber
eventBus.invokeSubscriber(pendingPost);
// handleMessage
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) { //
if (!sendMessage(obtainMessage())) { //
throw new EventBusException("Could not send handler message"); //
}
rescheduled = true;
return;
}
}
} finally {
handlerActive = rescheduled;
}
}
}
HandlerPosterは、実はHandlerの実装であり、内部でPendingPostQueueのメッセージキューを維持し、enqueue(Subscription subscription,Object event)メソッドでpendingPostPoolのArrayListキャッシュプールからPendingPostをPendingPostに追加し、そのPendingPostQueueイベントをHandlerに送信して処理する.
handleMessageでは、1つのwhileデッドサイクルにより、PendingPostQueueからPendingPostを取り出して実行し続け、postを取得した後、eventBusがそのpostを通じて対応するSubscriber処理イベントを検索する.
/**
* Posts events in background.
*
* @author Markus
*/
final class BackgroundPoster implements Runnable, Poster {
.....
@Override
public void run() {
try {
try {
// PendingPostQueue pendingPost eventBus
while (true) {
// 1000 PendingPostQueue pendingPost
PendingPost pendingPost = queue.poll(1000);
// pendingPost null
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll(); // pendingPost
if (pendingPost == null) {
executorRunning = false;
return;
}
}
}
// pendingPost EventBus
// PendingPostQueue 【 】 pendingPost , AsyncPoster
eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException e) {
eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", e);
}
} finally {
executorRunning = false;
}
}
}
BackgroundPosterが実現したのはRunnableで、私たちはそのrun方法を見て、PendingPostQueueからpendingPostをEventBusに取り出して配布し続け、ここで外部がwhile()死循環であることに注意して、PendingPostQueueの中のすべてのpendingPostが配布されることを意味します.なぜなら、BackGroundThreadバックグラウンドスレッドは、これが唯一なので、このスレッドに送信されたイベントはキューに配置され、購読時にループしてすべて送信される必要があります.
class AsyncPoster implements Runnable, Poster {
.....
@Override
public void run() {
PendingPost pendingPost = queue.poll();
if(pendingPost == null) {
throw new IllegalStateException("No pending post available");
}
// pendingPost EventBus
eventBus.invokeSubscriber(pendingPost);
}
}
3つのposterで使用されるキューPendingPostQueue:
final class PendingPostQueue {
private PendingPost head; //
private PendingPost tail; //
//
synchronized void enqueue(PendingPost pendingPost) {
if (pendingPost == null) {
throw new NullPointerException("null cannot be enqueued");
}
if (tail != null) { //
tail.next = pendingPost;
tail = pendingPost;
} else if (head == null) { //
head = tail = pendingPost; // ,
} else {
throw new IllegalStateException("Head present, but no tail"); //
}
notifyAll(); //
}
synchronized PendingPost poll() {
PendingPost pendingPost = head;
if (head != null) {
head = head.next;
if (head == null) {
tail = null;
}
}
return pendingPost;
}
synchronized PendingPost poll(int maxMillisToWait) throws InterruptedException {
if (head == null) {
wait(maxMillisToWait);
}
return poll();
}
}
final class PendingPost {
// ArrayList PendingPost
private final static List pendingPostPool = new ArrayList();
Object event;
Subscription subscription;
PendingPost next;
private PendingPost(Object event, Subscription subscription) {
this.event = event;
this.subscription = subscription;
}
// PendingPost
static PendingPost obtainPendingPost(Subscription subscription, Object event) {
synchronized (pendingPostPool) {
int size = pendingPostPool.size();
if (size > 0) {
PendingPost pendingPost = pendingPostPool.remove(size - 1); // PendingPost,
pendingPost.event = event;
pendingPost.subscription = subscription;
pendingPost.next = null;
return pendingPost;
}
}
return new PendingPost(event, subscription); // pendingPostPool
}
// PendingPost
static void releasePendingPost(PendingPost pendingPost) {
pendingPost.event = null;
pendingPost.subscription = null;
pendingPost.next = null;
synchronized (pendingPostPool) {
// Don't let the pool grow indefinitely
if (pendingPostPool.size() < 10000) { //
pendingPostPool.add(pendingPost);
}
}
}
}
5.ログアウト
EventBus.getDefault().unregister(this);
public synchronized void unregister(Object subscriber) {
List> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
登録プロセスでは、typesBySubscriberがサブスクライバのすべてのサブスクライバイベントタイプを保存するMapであることがわかります.ここでは、サブスクライバに基づいてサブスクライバイベントタイプリストを取得し、1つずつサブスクライバをキャンセルし、最後にtypesBySubscriberがサブスクライバを削除します.
/**
* Only updates subscriptionsByEventType, not typesBySubscriber! Caller must update typesBySubscriber.
* subscriptionByEventType, typesbysubscriber! typesbysubscriber。
*/
private void unsubscribeByEventType(Object subscriber, Class> eventType) {
List subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
subscriptionsByEventTypeはイベントタイプ対応サブスクリプション情報を格納するMapであり、コードロジックが非常に明確で、あるイベントタイプのサブスクリプション情報リストを探し出し、サブスクリプション情報を遍歴し、サブスクリプションをキャンセルするサブスクライバとサブスクリプション情報をカプセル化するサブスクライバとを対比し、同一であれば、そのサブスクリプション情報が失効することを説明し、そのサブスクリプション情報を除去する.