至于RxBus的原理在这儿就不讲了,这儿附上两个RxBus类和使用方法,一个只有两个方法(构造方法和发送消息方法),另一个多了事件订阅、取消时间订阅等一些方法。我使用的是第一个,因为第二个中多余的方法根本用不到... ...
还请大牛指点其中要害之处及利弊关系!感激不尽!!!
--------------------start---------------
废话不多说,两个分别展示一下:
再啰嗦一句:jar包别忘了!
compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1'
一:简单RxBus类及使用方法:(推荐)
1:RxBus类:
public class RxBus { private static volatile RxBus defaultInstance; private final Subject<Object, Object> bus; // PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者 public RxBus() { bus = new SerializedSubject<>(PublishSubject.create()); } // 单例RxBus public static RxBus getDefault() { if (defaultInstance == null) { synchronized (RxBus.class) { if (defaultInstance == null) { defaultInstance = new RxBus(); } } } return defaultInstance ; } // 发送一个新的事件 public void post (Object o) { bus.onNext(o); } // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者 public <T> Observable<T> toObservable (Class<T> eventType) { return bus.ofType(eventType); } }
2:使用方法:
2.1:在你想接收消息的地方订阅事件!注:任何地方
/** * 事件监听 */ @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) public void doSubscribe() { RxBus.getDefault().toObservable(RxBean.class) //在io线程进行订阅,可以执行一些耗时操作 .subscribeOn(Schedulers.io()) //在主线程进行观察,可做UI更新操作 .observeOn(AndroidSchedulers.mainThread()) //观察的对象 .subscribe(new Action1<RxBean>() { @Override public void call(RxBean rxBean) { /** *create by Davide *我这里只有一个Bean类,是通过status区分消息类型的,当然你可以分别注测不同的Bean类 */ switch (rxBean.getStatus()) { case 0: // ... ... break; case 1: // ... ... break; default: break; } } }); }
2.2:发送消息
RxBus.getDefault().post(new RxBean(Config.GAME_DETAIL_CURRENT_PAGE, "你可以通过自定义构造方法,发送任意你需要的参数"));
2.3:附上我的RxBean类吧,我懒,将所有的东西全部写在了一个Bean类里,通过不同的status区分消息类型,通过不同的构造方法传递参数。随着开发不断进行,不断添加构造方法,感觉比挨个写类方便多了,但是我还是想问问各位大牛们,这样会不会有什么弊端?
/** * @author Davide create on 17/7/31. * @email suwei@acooo.cn * Learn from yesterday, live for today, hope for tomorrow. */ public class RxBean { private int status; private int intId; private String id; private String imageUrl; private DownloadTask task; private boolean isTrue; private boolean hasFocus; private int focusIndex; private String apkName; private Uri uri; private MotionEvent event; private View view; public RxBean(int status, MotionEvent event) { this.status = status; this.event = event; } public RxBean(int status, Uri uri) { this.status = status; this.uri = uri; } public RxBean(int i, View view) { this.status = i; this.view = view; } public RxBean(int status, boolean isTrue) { this.status = status; this.isTrue = isTrue; } public RxBean(int status, int intId) { this.status = status; this.intId = intId; } public RxBean(int status, String id, int focusIndex) { this.status = status; this.id = id; this.focusIndex = focusIndex; } public RxBean(int movieFocusView, View v, boolean hasFocus) { this.status = movieFocusView; this.view = v; this.hasFocus = hasFocus; } public RxBean(int status, String id) { this.status = status; this.id = id; } public RxBean(int status, String id, boolean isTrue, DownloadTask task) { this.status = status; this.id = id; this.isTrue = isTrue; this.task = task; } public RxBean(int status, String id, boolean isTrue) { this.status = status; this.id = id; this.isTrue = isTrue; } public RxBean(int status, DownloadTask task) { this.status = status; this.task = task; } public RxBean(int status, String id, String imageUrl) { this.status = status; this.id = id; this.imageUrl = imageUrl; } public RxBean(int status, boolean isTrue, int focusIndex) { this.status = status; this.isTrue = isTrue; this.focusIndex = focusIndex; } public RxBean(int gameFocuesChangeTrueId, String pName, boolean isTrue, DownloadTask task, boolean hasFocus, int focusIndex, String apkName) { this.status = gameFocuesChangeTrueId; this.id = pName; this.isTrue = isTrue; this.task = task; this.hasFocus = hasFocus; this.focusIndex = focusIndex; this.apkName = apkName; } public View getView() { return view; } public void setView(View view) { this.view = view; } public MotionEvent getEvent() { return event; } public void setEvent(MotionEvent event) { this.event = event; } public Uri getUri() { return uri; } public void setUri(Uri uri) { this.uri = uri; } public String getApkName() { return apkName; } public void setApkName(String apkName) { this.apkName = apkName; } public int getFocusIndex() { return focusIndex; } public void setFocusIndex(int focusIndex) { this.focusIndex = focusIndex; } public boolean isHasFocus() { return hasFocus; } public void setHasFocus(boolean hasFocus) { this.hasFocus = hasFocus; } public boolean isTrue() { return isTrue; } public void setTrue(boolean aTrue) { isTrue = aTrue; } public int getIntId() { return intId; } public void setIntId(int intId) { this.intId = intId; } public String getImageUrl() { return imageUrl; } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public DownloadTask getTask() { return task; } public void setTask(DownloadTask task) { this.task = task; } public RxBean(int status) { this.status = status; } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getId() { return id; } public void setId(String id) { this.id = id; } @Override public String toString() { return "RxBean{" + "status=" + status + ", intId=" + intId + ", id='" + id + '\'' + ", imageUrl='" + imageUrl + '\'' + ", task=" + task + ", isTrue=" + isTrue + ", hasFocus=" + hasFocus + ", focusIndex=" + focusIndex + ", apkName='" + apkName + '\'' + ", uri=" + uri + ", event=" + event + ", view=" + view + '}'; } }
二:详细RxBean类:哪位大牛来帮我分析下利弊?
1:RxBus类及工具类:
public class RxBus { private final Subject<Object, Object> bus; private Map<Object, List<Subscription>> subscriptions; private RxBus() { //非线程安全的PublishSubject包装成线程安全的SerializedSubject bus = new SerializedSubject<>(PublishSubject.create()); } public static RxBus getDefault() { return SingletonHolder.INSTANCE; } /** * 发送事件 * * @param event 事件对象 */ public void post(Object event) { if (bus.hasObservers()) { bus.onNext(event); } } /** * 订阅事件 * * @param subscriber 订阅者 * @param callback 事件回调 * @param <T> 事件类型 */ public <T> void subscribe(Object subscriber, Callback<T> callback) { Class<T> eventType = RawType.getRawType(callback); Subscription subscription = bus.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .ofType(eventType) .subscribe(callback); add(subscriber, subscription); } /** * 订阅事件 * * @param subscriber 订阅者 * @param eventType 事件对象 * @param callback 事件回调 * @param <T> 事件类型 */ public <T> void subscribe(Object subscriber, Class<T> eventType, Callback<T> callback) { Subscription subscription = bus.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .ofType(eventType) .subscribe(callback); add(subscriber, subscription); } /** * 订阅事件 * * @param eventType 事件对象 * @param callback 事件回调 * @param <T> 事件类型 */ public <T> Subscription subscribe(Class<T> eventType, Callback<T> callback) { return bus.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .ofType(eventType) .subscribe(callback); } /** * 订阅事件 * * @param eventType 事件对象 * @param <T> 事件类型 * @return 特定类型的Observable */ public <T> Observable<T> observe(Class<T> eventType) { return bus.ofType(eventType); } /** * 添加订阅协议 * * @param subscriber 订阅者 * @param subscription 订阅协议 */ public synchronized void add(Object subscriber, Subscription subscription) { if (subscriptions == null) { subscriptions = new HashMap<>(); } List<Subscription> list = subscriptions.get(subscriber); if (list == null) { list = new ArrayList<>(); } list.add(subscription); subscriptions.put(subscriber, list); } /** * 取消事件订阅 * * @param subscriber 订阅者 */ public synchronized void unsubscribe(Object subscriber) { if (subscriptions == null) return; List<Subscription> list = subscriptions.get(subscriber); if (list == null || list.isEmpty()) return; for (Subscription subscription : list) { subscription.unsubscribe(); } list.clear(); subscriptions.remove(subscriber); } /** * 取消所有订阅 */ public void unsubscribeAll() { Set<Map.Entry<Object, List<Subscription>>> set = subscriptions.entrySet(); for (Map.Entry<Object, List<Subscription>> entry : set) { List<Subscription> list = entry.getValue(); for (Subscription subscription : list) { subscription.unsubscribe(); } list.clear(); } subscriptions = null; } private static class SingletonHolder { public static volatile RxBus INSTANCE = new RxBus(); } public <T> Observable<T> toObservable (Class<T> eventType) { return bus.ofType(eventType); } public <T> Observable<T> IoToUiObservable(Class<T> eventType){ return bus.ofType(eventType) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }
public abstract class Callback<T> implements Action1<T> { /** * 监听到事件时回调接口 * * @param t 返回结果 */ public abstract void onEvent(T t); @Override public void call(T t) { onEvent(t); } }
public class RawType { public static <T> Class<T> getRawType(Callback<T> callback) { Type genericSuperclass = callback.getClass() .getGenericSuperclass(); Type[] params = ((ParameterizedType) genericSuperclass).getActualTypeArguments(); Type type = params[0]; return (Class<T>) getRawType(type); } private static Class<?> getRawType(Type type) { if (type == null) throw new NullPointerException("type == null"); if (type instanceof Class<?>) { // Type is a normal class. return (Class<?>) type; } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but // suspects some pathological case related to nested classes exists. Type rawType = parameterizedType.getRawType(); if (!(rawType instanceof Class)) throw new IllegalArgumentException(); return (Class<?>) rawType; } if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0) .getClass(); } if (type instanceof TypeVariable) { // We could use the variable's bounds, but that won't work if there are multiple. Having a raw // type that's more general than necessary is okay. return Object.class; } if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + type.getClass() .getName()); } }
2:使用方法基本相同:
2.1:订阅事件略有不同
定义全局变量
private CompositeSubscription mCompositeSubscription;
初始化:
mCompositeSubscription = new CompositeSubscription();
订阅事件:
mCompositeSubscription.add(RxBus.getDefault() .toObservable(RxBean.class)//bean类随意定义 .sample(16, TimeUnit.MILLISECONDS) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(totalJunkSizeEvent -> { // ... ... 你的操作 }, Throwable::printStackTrace));
记得取消订阅:一般在Destroy等退出的地方,如果不取消订阅,可能会造成内存溢出或者页面无法销毁等,但是或许在有的时候你会选择故意不取消订阅也说不定!
if (mCompositeSubscription.isUnsubscribed()) { this.mCompositeSubscription.unsubscribe(); } this.mCompositeSubscription = null;
感觉有点复杂,其实关键的接收代码基本没差。
2.2:发送消息
RxBus.getDefault().post(new RxBean(Config.GAME_DETAIL_CURRENT_PAGE,
"你可以通过自定义构造方法,发送任意你需要的参数,也可以自定义Bean类"));
2.3: Bean类不再展示,随你定义
参考博文:丢失
-------------------------end-------------------