【EventBus】EventBus 源码解析 ( 事件发送 | 发布线程为 子线程 切换到 主线程 执行订阅方法的过程分析 )

举报
韩曙亮 发表于 2022/01/13 22:27:22 2022/01/13
【摘要】 文章目录 一、EventBus 中主线程支持类二、MainThreadSupport 解析三、MainThreadSupport 解析四、PendingPost 链表 一、E...





一、EventBus 中主线程支持类



EventBus.postToSubscription 方法中 , 如果当前线程是子线程 , 则调用如下方法 , 切换到主线程执行 ;

                	// 假如发布线程是子线程 , 则将事件加入队列 , 通过 Handler 切换线程执行 
                    mainThreadPoster.enqueue(subscription, event);

  
 
  • 1
  • 2

mainThreadPoster 是通过 mainThreadSupport.createPoster(this) 创建的 ;

注意 , 创建 mainThreadPoster 时 , 会判定当前线程是否是主线程 , 如果当前线程是主线程 , 才会创建 mainThreadPoster , 否则为空 ;

EventBus 中 mainThreadPoster 相关代码 :

public class EventBus {
    // @Nullable
    private final MainThreadSupport mainThreadSupport;
    // @Nullable
    private final Poster mainThreadPoster;

    EventBus(EventBusBuilder builder) {
        mainThreadSupport = builder.getMainThreadSupport();
        // 如果当前线程是主线程 , 才会创建 mainThreadPoster , 否则为空
        mainThreadPoster = mainThreadSupport != null ? mainThreadSupport.createPoster(this) : null;
    }
    private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    	// 获取该 订阅方法 的线程模式 
        switch (subscription.subscriberMethod.threadMode) {
            case MAIN:
                if (isMainThread) {
                	// 假如在主线程中 , 直接调用 
                    invokeSubscriber(subscription, event);
                } else {
                	// 假如发布线程是子线程 , 则将事件加入队列 , 通过 Handler 切换线程执行 
                    mainThreadPoster.enqueue(subscription, event);
                }
                break;
		}
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26




二、MainThreadSupport 解析



MainThreadSupport 是一个接口 , 在 AndroidHandlerMainThreadSupport 实现类中的 createPoster 方法中 , 创建了一个 HandlerPoster ;

package org.greenrobot.eventbus;

import android.os.Looper;

/**
 * 接口到“主”线程,可以是您喜欢的任何线程。通常在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);
        }
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33




三、MainThreadSupport 解析



调用 mainThreadSupport.createPoster(this) 创建的对象就是 HandlerPoster 对象 , 其本质是一个 Handler ;

调用 void enqueue(Subscription subscription, Object event) 方法 , 将订阅者和订阅方法 , 事件对象 传入该方法 , 将 订阅者 和 事件对象 加入到 PendingPost 链表中 ;

同时调用 sendMessage(obtainMessage()) 方法 , 向 Handler 发送消息 , 执行 handleMessage 方法中的业务逻辑 ;

handleMessage 方法中 , PendingPost pendingPost = queue.poll() 取出链表元素 , 每个元素中封装了 订阅者 和 事件对象 , eventBus.invokeSubscriber(pendingPost); 通过反射执行订阅方法 ;


HandlerPoster 源码 :

public class HandlerPoster extends Handler implements Poster {
    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    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) {
    	// PendingPost 是一个链表数据结构 , 将所有的 事件对象 , 订阅者 都封装在了该链表中 ; 
    	//		将 订阅者 和 事件对象 加入到 PendingPost 链表中 
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized (this) {
            queue.enqueue(pendingPost);
            if (!handlerActive) {
                handlerActive = true;
                // 向 Handler 发送消息 , 执行 handleMessage 方法
                if (!sendMessage(obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }
        }
    }

	// 不断取出 PendingPost 链表中的数据 , 执行订阅方法 
    @Override
    public void handleMessage(Message msg) {
        boolean rescheduled = false;
        try {
            long started = SystemClock.uptimeMillis();
            while (true) {
            	// 取出链表元素 , 每个元素中封装了 订阅者 和 事件对象
                PendingPost pendingPost = queue.poll();
                if (pendingPost == null) {
                    synchronized (this) {
                        // Check again, this time in synchronized
                        pendingPost = queue.poll();
                        if (pendingPost == null) {
                            handlerActive = false;
                            return;
                        }
                    }
                }
                
                // 通过反射执行订阅方法 
                eventBus.invokeSubscriber(pendingPost);
                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;
        }
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66




四、PendingPost 链表



PendingPost 是一个链表数据结构 , 将所有的 事件对象 , 订阅者 都封装在了该链表中 ;

final class PendingPost {
    private final static List<PendingPost> pendingPostPool = new ArrayList<PendingPost>();

    Object event;
    Subscription subscription;
    PendingPost next;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/120462534

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。