EventBus 소스 검토(아래)

31108 단어 android 진급

post () 방법 호출 프로세스


계속해서 EventBus류의 또 다른 입구 방법post()을 살펴보겠습니다.
//       
public void post(Object event) {
    PostingThreadState postingState = currentPostingThreadState.get();
    List<Object> eventQueue = postingState.eventQueue;
    eventQueue.add(event);

    if (!postingState.isPosting) {
        postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
        postingState.isPosting = true;
        if (postingState.canceled) {
            throw new EventBusException("Internal error. Abort state was not reset");
        }
        while (!eventQueue.isEmpty()) {
            postSingleEvent(eventQueue.remove(0), postingState);
        }
        postingState.isPosting = false;
        postingState.isMainThread = false;
    }
}

post () 방법은 우선 currentPostingThreadState 대상에서 하나 PostingThreadState 를 가져왔습니다. 이currentPostingThreadState 대상의 생성 코드를 보십시오. 
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new
ThreadLocal<PostingThreadState>() {
    @Override
    protected PostingThreadState initialValue() {
        return new PostingThreadState();
    }
};
ThreadLocal는 스레드 내부의 데이터 저장 클래스로 지정된 스레드에 데이터를 저장할 수 있으며 이 데이터는 다른 스레드와 공유되지 않는다.그 내부 원리는 그것을 감싸는 범용 대상의 수조를 생성하는 것이다. 서로 다른 라인에 서로 다른 수조 인덱스 값이 있을 수 있다. 이를 통해 모든 라인이 get() 방법을 통해 얻을 때 자신의 라인에 대응하는 데이터만 얻을 수 있다.Event Bus에서 Thread Local이 감싸는 것은 PostingThreadState 클래스로 이벤트 발송 과정에 필요한 데이터만 봉인할 뿐이다. 
final static class PostingThreadState {
    //  post           
    final List<Object> eventQueue = new ArrayList<Object>(); 
    boolean isPosting; //      postSingleEvent()  
    boolean isMainThread;
    Subscription subscription;
    Object event;
    boolean canceled;
    }

다시 post() 방법으로 돌아가면 핵심 코드가 이 문장인 것을 알 수 있다.
while (!eventQueue.isEmpty()) {
    postSingleEvent(eventQueue.remove(0), postingState);
}

호출할 때마다 post() 이벤트가 전송되며, 이 이벤트는 대기열에 추가됩니다.매번 실행postSingleEvent()할 때마다 대기열에서 이벤트를 꺼냅니다. 이렇게 하면 대기열이 모두 꺼질 때까지 이벤트 처리를 끊임없이 꺼냅니다.PostSingle Event () 방법 다시 보기
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
    Class> eventClass = event.getClass();
    boolean subscriptionFound = false;
    if (eventInheritance) {
        //   eventClass       
        List<Class>> eventTypes = lookupAllEventTypes(eventClass);
        int countTypes = eventTypes.size();
        for (int h = 0; h < countTypes; h++) {
            Class> clazz = eventTypes.get(h);
            //             ,     
            subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
        }
    } else {
        subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
    }
    if (!subscriptionFound) {
        if (logNoSubscriberMessages) {
            Log.d(TAG, "No subscribers registered for event " + eventClass);
        }

        //  sendNoSubscriberEvent  
        if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
                eventClass != SubscriberExceptionEvent.class) {
            post(new NoSubscriberEvent(this, event));
        }
    }
}

Event Bus Build에서 eventInheritance 뭐 했는지 기억나세요?이것은 하위 클래스 이벤트가 부모 클래스에 응답할 수 있는지 onEvent() 방법을 나타낸다.다시 아래를 보면 lookupAllEventTypes() 순환과 귀속을 통해 한 종류의 부류, 인터페이스, 부류의 인터페이스, 부류 인터페이스의 부류를 전체 정적 변수 eventTypes 집합에 추가합니다.전역 정적 변수를 사용하는 장점은 전역 정적 변수를 사용하면 시간이 걸리고 복잡한 순환 + 귀속 방법을 한 번만 실행하면 된다는 것이다. 다음에는 키: 이벤트 클래스를 통해 이 이벤트의 여부와 lookupAll Event Types () 방법을 실행했는지 판단하기만 하면 된다. 

postSingle EventFor EventType () 방법


그리고 우리는 계속해서 아래로 내려가서 발송 방법을 보았다postSingleEventForEventType()
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class> eventClass) {
    CopyOnWriteArrayList<Subscription> subscriptions;
    synchronized (this) {
        //     eventClass     
        subscriptions = subscriptionsByEventType.get(eventClass);
    }
    if (subscriptions != null && !subscriptions.isEmpty()) {
        //  subscription     
        for (Subscription subscription : subscriptions) {
            postingState.event = event;
            postingState.subscription = subscription;
            boolean aborted = false;
            try {
                postToSubscription(subscription, event, postingState.isMainThread);
                aborted = postingState.canceled;
            } finally {
                postingState.event = null;
                postingState.subscription = null;
                postingState.canceled = false;
            }
            if (aborted) {
                break;
            }
        }
        return true;
    }
    return false;
}

얘가 먼저 이 구절을 통과했어요.
subscriptions = subscriptionsByEventType.get(eventClass);

이벤트클래스를 구독한 모든 이벤트 집합을 가져옵니다. 앞서 말했듯이,subscriptions By Event Type은 키: 구독한 이벤트value: 이 이벤트를 구독한 모든 구독자가 집합한 맵입니다.마지막으로 이벤트클래스 이벤트를 구독한 모든 구독자를 순환하여 구독자마다 이벤트를 보냅니다.이벤트를 보내는 방법을 보십시오: postToSubscription(subscription, event, postingState.isMainThread); 아, 이전의Subscribe 프로세스에서 점착 이벤트를 처리하는 방법과 같은 방법으로 돌아왔습니다. - 서로 다른 라인 모드를 설명하는 이벤트에 대해 서로 다른 응답 방법을 했고 결국은 invokeSubscriber() 구독자류에서 onEvent로 시작하는 반사 방법을 통과했습니다. 

unregister()


계속해서 EventBus류, 마지막 입구 방법unregister()을 살펴보겠습니다.
public synchronized void unregister(Object subscriber) {
    List<Class>> subscribedTypes = typesBySubscriber.get(subscriber);
    if (subscribedTypes != null) {
        for (Class> eventType : subscribedTypes) {
            //    subscriber eventType     
            unsubscribeByEventType(subscriber, eventType);
        }
        // subscriber           ,     
        typesBySubscriber.remove(subscriber);
    }
}

앞서 말했듯이typesBySubscriberkey: 구독자 대상value: 이 구독자가 구독하는 이벤트 집합은 현재 구독자가 어떤 이벤트를 구독하고 있는지 나타낸다.먼저 등록을 취소할 구독자의 구독을 두루 훑어보고 unsubscribeByEventType()를 호출합니다. 이 사건의 모든 구독자 집합에서 등록을 취소할 구독자를 제거합니다.마지막으로: 현재 구독자가 키의 모든 구독 이벤트를value로 집합한 Map 의 Entry를 제거하면 등록을 취소하는 모든 과정이 완료됩니다.

EventBus 작동 방식


마지막으로 디자이너의 관점에서 EventBus의 작업 원리를 살펴보자.

구독의 논리


1. 우선register() 방법을 사용하여 구독자 A를 등록한다.2. 이 구독자 A의 전부 onEvent로 시작하는 구독 방법.3. A가 구독한 모든 이벤트를 키로 하고 키 이벤트에 응답할 수 있는 모든 구독자의 집합을value로 하여 Map>에 저장한다.4. A의 클래스 이름은 키이고 모든 onEvent 매개 변수 유형의 클래스 이름으로 구성된 집합은value로Map>에 저장됩니다.4.1 만약에 점착 이벤트를 구독한 구독자라면 점착 이벤트 캐시에서 이전에 보낸 점착 이벤트를 가져와 이 점착 이벤트에 응답한다.

발송 이벤트의 논리


1. 현재 라인의 송신 이벤트 봉인 데이터를 취하고 봉인된 데이터에서 송신 이벤트의 이벤트 대기열을 가져옵니다.2. 보낼 이벤트를 이벤트 대기열에 추가합니다.3. 순환, 매번 대기열에 있는 이벤트를 모든 구독자에게 발송합니다.3.1 만약에 하위 이벤트가 부모 이벤트에 응답할 수 있는 이벤트 모델이라면 이 이벤트의 모든 부류, 인터페이스, 부류의 인터페이스, 부류 인터페이스의 부류를 먼저 찾아내고 이 부류 정보를 구독한 구독자도 이 이벤트에 응답하도록 해야 한다. 

응답 이벤트의 논리


1. 발송 이벤트 처리가 완료되면 이벤트는 응답을 담당하는 논리적인 부분에 맡긴다.2. 먼저 시간의 응답 모드를 판단하고 응답 모드는 네 가지로 나뉜다. PostThread가 어느 라인에서 호출된post() 방법은 어느 라인에서 응답 방법을 실행하는가이다.MainThread는 어느 라인에서 호출되었든지 post() 방법은 최종적으로 주 라인에서 응답 방법을 실행합니다.BackgroundThread는 어느 라인에서 호출되었든지 post() 방법은 최종적으로 백엔드 라인에서 응답 방법을 실행합니다.(직렬 실행, 한 번에 한 작업만 수행하고 다른 작업은 대기열에서 대기 상태) Async는 어느 라인에서 호출된 post() 방법이든 백엔드 라인에서 응답 방법을 수행합니다.(병렬 실행, 임무가 있으면 라인을 하나 열어 실행시킨다)

등록 취소 논리


1. 먼저 unregister() 방법을 사용해서 등록을 취소할 구독자 B를 받는다.2、이 클래스를 구독할 때 저장된Map>에서 이 클래스의 구독 이벤트 집합을 가져옵니다.3. 구독 시간 집합을 누비고 가입할 때 저장된Map>에서 구독 이벤트에 대응하는 구독자 집합 중의 이 구독자를 제거합니다.4, 단계 2의 Map>에서 이 구독자와 관련된 Entry를 제거합니다. 

작동 원리 그래픽

좋은 웹페이지 즐겨찾기