天天看點

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<String, Serializable> 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<String, Serializable>();
        }
        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<String, List<EventListener>> listenerMap = new HashMap<String, List<EventListener>>();
    private final Map<String, List<Event>> stickyEvents = new HashMap<String, List<Event>>();

    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<EventListener> listeners = listenerMap.get(name);
            if (listeners == null) {
                listeners = new ArrayList<EventListener>();
                listenerMap.put(name, listeners);
            }
            listeners.add(listener);
        }

        List<Event> 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<EventListener> 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<Event> 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<Event> events = stickyEvents.get(event.getName());
            if (events == null) {
                events = new ArrayList<Event>();
                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<EventListener> 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();
    }
}      

以上代碼由 薄荷記賬 研發團隊原創并分享,轉載請加注此行。

繼續閱讀