200行代码实现Android事件总线框架

之所以说200行,并非突出代码的简洁和优秀,而是表达事情的本来面目就是这样,我们没必要把简单的事情搞的那么复杂。

像Greenrobot的EventBus,又是发布/订阅模式,又是线程模型,特别是其基于反射的实现,在Android系统生态越来越封闭的倾向下,适应性将是个问题。无论其搞的什么花花概念,其本质都是基于静态引用。

我们扪心自问,事件总线是干什么的?不就是给你发个消息,让你干件事情嘛!对,静态引用即可。至于怎么弄,请看代码。

以下代码可以保证的是:

1、一看就懂,0学习成本,没有乱七八糟的概念,随自己需要快速二次开发;

2、功能完整,支持事件参数传递,支持发送粘性事件;

3、运行稳定,无额外开销,适应性强;

4、监听器确保在主线程点火,不管从何处发出事件。如有需要可改在子线程点火,但会有额外开销,增加整个项目线程的管控难度。反正我们不需要在子线程,就那么几个破事件,发一下就得了,在主线程快速执行......

一、首先是事件结构定义:重要的是支持各种参数传递

import android.text.TextUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

public class Event implements Serializable {
   
    private final String name;
    private Map data;

    public Event(String name) {
        if (TextUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Event name is null.");
        }
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Event put(String key, Serializable value) {
        if (data == null) {
            data = new HashMap();
        }
        data.put(key, value);
        return this;
    }

    public Serializable get(String key) {
        if (data == null) {
            return null;
        }
        return data.get(key);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Event:" + name);
        if (data != null) {
            sb.append("," + data.toString());
        }
        return sb.toString();
    }
}

二、监听器定义

public interface EventListener {
    public void onReceive(Event event);
}

三、事件总线处理器:支持发送粘性事件

import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EventBus {
    private static volatile EventBus instance;

    public static EventBus getInstance() {
        if (instance == null) {
            synchronized (EventBus.class) {
                if (instance == null) {
                    instance = new EventBus();
                }
            }
        }
        return instance;
    }

    private final Map> listenerMap = new HashMap>();
    private final Map> stickyEvents = new HashMap>();

    private final Handler handler = new Handler(Looper.getMainLooper());

    public void register(String name, EventListener listener) {
        if (TextUtils.isEmpty(name)) {
            throw new NullPointerException("name is null.");
        }

        if (listener == null) {
            throw new NullPointerException("listener is null.");
        }

        synchronized (listenerMap) {

            List listeners = listenerMap.get(name);
            if (listeners == null) {
                listeners = new ArrayList();
                listenerMap.put(name, listeners);
            }
            listeners.add(listener);
        }

        List events = null;
        synchronized (stickyEvents) {
            events = stickyEvents.get(name);
        }

        if (events != null && !events.isEmpty()) {
            for (int i = 0; i < events.size(); i++) {
                Event event = events.get(i);
                fireListener(event, listener);
            }
        }
    }

    public void unregister(String name, EventListener listener) {
        if (TextUtils.isEmpty(name)) {
            return;
        }

        if (listener == null) {
            return;
        }

        synchronized (listenerMap) {
            List listeners = listenerMap.get(name);
            if (listeners == null) {
                return;
            }
            listeners.remove(listener);
        }
    }

    public void unregisterAll(String name) {
        if (TextUtils.isEmpty(name)) {
            return;
        }

        synchronized (listenerMap) {
            listenerMap.remove(name);
        }
    }

    public void clear() {
        synchronized (listenerMap) {
            listenerMap.clear();
        }
    }

    public void sendEvent(String name) {
        sendEvent(new Event(name));
    }

    public void sendStickyEvent(String name) {
        sendStickyEvent(new Event(name));
    }

    public void removeStickyEvent(Event event) {
        if (event == null) {
            return;
        }

        synchronized (stickyEvents) {
            List events = stickyEvents.get(event.getName());
            if (events == null) {
                return;
            }
            events.remove(event);
        }
    }

    public void removeStickyEvents(String name) {
        synchronized (stickyEvents) {
            stickyEvents.remove(name);
        }
    }

    public void clearStickyEvents() {
        synchronized (stickyEvents) {
            stickyEvents.clear();
        }
    }

    public void sendStickyEvent(final Event event) {
        if (event == null) {
            throw new NullPointerException("event is null.");
        }

        synchronized (stickyEvents) {
            List events = stickyEvents.get(event.getName());
            if (events == null) {
                events = new ArrayList();
                stickyEvents.put(event.getName(), events);
            }
            events.add(event);
        }

        sendEvent(event);
    }

    public void sendEvent(final Event event) {
        if (event == null) {
            throw new NullPointerException("event is null.");
        }

        List listeners = null;

        synchronized (listenerMap) {
            listeners = listenerMap.get(event.getName());
        }

        if (listeners == null || listeners.isEmpty()) {
            return;
        }

        for (int i = 0; i < listeners.size(); i++) {
            final EventListener listener = listeners.get(i);
            fireListener(event, listener);
        }
    }

    private void fireListener(final Event event, final EventListener listener) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                listener.onReceive(event);
            }
        });
    }


    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        listenerMap.clear();
    }
}

以上代码由 薄荷记账 研发团队原创并分享,转载请加注此行。

你可能感兴趣的:(200行代码实现Android事件总线框架)