改良EventBus

EventBus给android应用开发带来了统一的生产消费设计模式,大大提升了模块解耦能力,但不同模块间任然存在编译依赖,对应更大型的工程,如不同插件(运行依赖)则支持有限,在此基础上,设计了一套全解耦的消息驱动模型,解决了模块的编译依赖。

将EventBus接口分装,做成消息驱动,简化接口

package com.jd.mall.data;

import java.util.HashMap;
import java.util.Map;

import de.greenrobot.event.EventBus;

/**
 * Created by zephyrluo on 2015/01/23.
 */
/*
register: ObserverMgr.register(this);
 */
public class ObserverEvent {
    private EventBus eb;
    private String observerKey;

    static Map<string observerevent=""> osi = new HashMap<string observerevent="">();

    public ObserverEvent(String s) {
        observerKey = s;
        eb=EventBus.getDefault();
        eb.register(this);
    }

    /*
    @hide
     */
    public void onEvent(Object val) {
        ObserverMgr.postInner(observerKey, val, ObserverMgr.FIRE_IN_SRC_THREAD);
    }
    /*
    @hide
     */
    public void onEventBackgroundThread(Object val) {
        ObserverMgr.postInner(observerKey, val, ObserverMgr.FIRE_IN_BG_THREAD);
    }

    /*
    @hide
     */
    public void onEventMainThread(Object val) {
        ObserverMgr.postInner(observerKey, val, ObserverMgr.FIRE_IN_UI_THREAD);
    }

    /*
    @hide
     */
    public void onEventAsync(Object val) {
        ObserverMgr.postInner(observerKey, val, ObserverMgr.FIRE_IN_ASYNC);
    }

    public static void post(String s, Object result) {
        ObserverEvent ob = ObserverEvent.obtain(s);
        ob.post(result);
    }


    public static ObserverEvent obtain(String s) {
        if(osi.containsValue(s)) return osi.get(s);
        ObserverEvent oi = new ObserverEvent(s);
        osi.put(s, oi);
        return oi;
    }

    public void post(Object result){
        eb.post(result);
    }
}


利用annotation特性,进一步简化接口

package com.jd.mall.data;

import android.os.Bundle;
import android.util.Pair;

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.ThreadMode;

/**
 * Created by luozhifan on 2015/01/13.
 */
public class ObserverMgr {
    final public static int FIRE_IN_SRC_THREAD = 1<<0;
    final public static int FIRE_IN_UI_THREAD = 1<<1;
    final public static int FIRE_IN_BG_THREAD = 1<<2;
    final public static int FIRE_IN_ASYNC = 1<<3;

    private static HashMap<Pair<String, Integer>, HashSet<Pair<Object, Method>>> obs
            = new  HashMap<Pair<String, Integer>, HashSet<Pair<Object, Method>>>();
    @Retention(RetentionPolicy.RUNTIME)
    public static @interface Observer{
        String key();
        int mode();
    }

    public static void register(Object subscriber){
        for(Method m:subscriber.getClass().getMethods()) {
            Observer ob = m.getAnnotation(Observer.class);
            if (ob==null) continue;
            String key = ob.key();
            int fireModes = ob.mode();
            for (int i=0; i<4; i++){
                int fireMode = 1<<i;
                if ((fireMode&fireModes) == 0) continue;
                Pair<String, Integer> keyPair = Pair.create(key, fireMode);
                if(!obs.containsKey(keyPair)) {
                    obs.put(keyPair, new HashSet<Pair<Object, Method>>());
                }
                obs.get(keyPair).add( Pair.create(subscriber, m) );
            }
        }
    }

    public static void unregister(Object subscriber){
        for(Method m:subscriber.getClass().getMethods()) {
            Observer ob = m.getAnnotation(Observer.class);
            if (ob==null) continue;
            String key = ob.key();
            int fireModes = ob.mode();
            for (int i=0; i<4; i++) {
                int fireMode = 1 << i;
                if ((fireMode & fireModes) == 0) continue;
                Pair<String, Integer> keyPair = Pair.create(key, fireMode);
                obs.get(keyPair).remove(Pair.create(subscriber, m));
            }
        }
    }

    public static void unregister(String key){
        for (int i=0; i<4; i++) {
            int fireMode = 1 << i;
            Pair<String, Integer> keyPair = Pair.create(key, fireMode);
            obs.remove(keyPair);
        }
    }

    static void postInner(String key, Object event, int mode){
        Pair<String, Integer> keyPair = Pair.create(key, mode);
        if(!obs.containsKey(keyPair)) return;
        for (Pair<Object, Method> cb : obs.get(keyPair)){
            try {
                cb.second.invoke(cb.first, event);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
使用例子,消息驱动处理如下:
    @ObserverMgr.Observer(key="Preference.test2",
            mode=ObserverMgr.FIRE_IN_SRC_THREAD|ObserverMgr.FIRE_IN_UI_THREAD|ObserverMgr.FIRE_IN_BG_THREAD|ObserverMgr.FIRE_IN_ASYNC)
    public void dataChanged(Object dat){
        JDLog.tag().i("dataChanged:"+dat.toString()+" trdid:"+Thread.currentThread().getName());
    }
调用例子如下:

    public void testPreference2() throws Exception {
        File dataDir = getInstrumentation().getTargetContext().getFilesDir();
        Preference p2 = Preference.obtain(dataDir, "test2");

        ObserverMgr.register(this);

        JDLog.tag().p("start ...");
        ObjTest ot = new ObjTest();
        ot.strtmp1 = "stage1";
        ot.strtmp2 = "tmp1";
        ot.tmp1=23;
        ot.ltmp3 = 123L;
        Thread.sleep(100);
    }

对应的Preference类的实现如下:

package com.jd.mall.data;

import android.os.Bundle;
import android.os.Parcel;

import com.jd.mall.control.logsys.JDLog;
import com.litl.leveldb.DB;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

/**
 * Created by luozhifan on 2015/01/12.
 *
 * process persistent bundle/object instance.
 * auto fire update event into Observer("Preference.<key>") in default way;
 * data save into leveldb with sync mode.
 */
public class Preference {

    private Bundle b = null;
    private Object obj = null;

    private String pkgName = "";
    private String observerKey;
    private boolean enableNotify = true;

//    private EventBus eb = new EventBus();
    private ObserverEvent oe;
    private static DB db = null ;
    private static HashMap<string preference=""> globalPfc = new HashMap<string preference="">();

    /*
    @param key: define a persistent set
     */
    private Preference(File datadir, String key) {
        pkgName = key;
        observerKey = "Preference."+pkgName;
        oe = ObserverEvent.obtain(observerKey);
//        eb.register(this);
        if(!globalPfc.containsKey(key)) globalPfc.put(key, this);
        if(db==null) {
            db = new DB(new File(datadir, Constant.PERFERENCE_DB_PATH));
            db.open();
        }
    }

    /*
    fetch singleton Preference instance

    @param key: a persistent set's name
     */
    static public Preference obtain(File datadir, String key) {
        if(!globalPfc.containsKey(key)) {
            new Preference(datadir, key);
        }
        return globalPfc.get(key);
    }

    /*
    fetch saved data, return a Bundle type value.
    can only use one of getBundle and get.
     */
     public final synchronized Bundle getBundle() {
         if (obj != null) return null;
         if (b != null) return b;

         b = new Bundle();
         byte[] ret = db.get(pkgName.getBytes());
         if(ret!=null) {
             Parcel parcel = Parcel.obtain();
             parcel.unmarshall(ret, 0, ret.length);
             parcel.setDataPosition(0);
             b.readFromParcel(parcel);
             parcel.recycle();
         }
         return b;
    }

    /*
    fetch saved val, return an any type value.
    can only use one of getBundle and get.
    */
    public final synchronized <t> T get()  {
        if (b != null) return null;
        if(obj!=null) return (T)obj;

        try {
            ByteArrayInputStream b = new ByteArrayInputStream(db.get(pkgName.getBytes()));
            ObjectInputStream o = new ObjectInputStream(b);
            obj = o.readObject();
            return (T)obj;
        } catch (Exception e) {
        }
        return null;
    }

    public void notifyObserver(boolean enable){
        enableNotify = enable;
    }


    public void update(Object val){
        obj = val;
        if(enableNotify) oe.post(val);
    }

    public void update(Bundle val){
        b = (Bundle) val;
        if(enableNotify) oe.post(val);
    }
    public synchronized void saveBundle(Bundle val) {
        Parcel parcel = Parcel.obtain();
        val.writeToParcel(parcel, 0);
        db.put(pkgName.getBytes(), parcel.marshall());
        parcel.recycle();
        if(enableNotify) oe.post(val);
    }

    public synchronized void save(Object val)  {
        try {
            ByteArrayOutputStream b = new ByteArrayOutputStream();
            ObjectOutputStream o = new ObjectOutputStream(b);
            o.writeObject(val);
            db.put(pkgName.getBytes(), b.toByteArray());
            if(enableNotify) oe.post(val);
        }
        catch(Exception e){
            JDLog.trace(e);
        }
    }
}

你可能感兴趣的:(改良EventBus)