为什么在项目中要慎用RxBus
RxBus在之前作为Android组件间通信工具,简单方便十分受欢迎。
- 针对在事件的发送者和订阅者之间进行解耦
- 非常好的运用在Activitys、Fragments和后台线程
- 避开了联系紧密易出错的依赖关系和容易出错生命周期
- 使你的代码更加简洁
##在Fragment之间传递数据
假设我们需要在AFragment
和BFragment
之间进行数据传递,如果不使用类似RxBus
这样的通信工具,我们需要使用__广播__或者__接口回调__等方式传递数据,这样极其繁琐且无法在其他地方需要使用时直接复用。
这里我们举例,将AFragment
中的一个EditText
的文本数据在有变化时,实时传递给BFragment
。
- 在
AFragment
监听数据并发送变化后的数据
public class AFragment extends BaseFragment {
@SuppressLint("CheckResult")
@Nullable
@Override
protected void onCreateView(View view) {
super.onCreateView(view);
//监听AFragment的et数据变化
RxTextView.afterTextChangeEvents(et)
.subscribe(event -> {
// RxBus.send(new TradeEvent.TextChange(event.toString()));
//使用RxBus发送数据,这里直接发送sticky事件,以模拟AFragment事件发生时,BFragment还未创建的情况
RxBus.send(true, new TradeEvent.TextChange(event.toString()));
});
}
@Override
protected int initLayout() {
return R.layout.fragment_a;
}
@Override
protected void subscribe() {
}
}
- 在
BFragment
监听变化后的数据
public class BFragment extends BaseFragment {
@SuppressLint("CheckResult")
@Override
protected void subscribe() {
RxBus.observable(TradeEvent.TextChange.class)
.subscribe(e -> {
//获取变化后的数据
LogHelper.d(e.s);
});
}
@Override
protected int initLayout() {
return R.layout.fragment_a;
}
}
这个例子中,我们只需要简单的在需要发送数据的地方实现RxBus.send()
,在需要接受数据的地方实现RxBus.observable()
即可完成整个逻辑。但是这样并不代表,我们可以在任何情况下都如此去传递数据。
在网络请求时传递数据
例如我们需要在跳转一个页面之前,请求这个页面的数据,并在页面创建之后使用这个数据展示页面,我们会这么写:
- 封装好的网络请求
/**
* 订单详情 调用后监听 OrderEvent.DetailChange
*
* @param orderId 订单Id
*/
public void orderDetail(String orderId) {
//防止之前的sticky事件还未被消费
RxBus.removeSticky(OrderEvent.DetailChange.class);
OrderDetailRequest json = new OrderDetailRequest(orderId);
RequestEntity entity = new RequestEntity(IdlefishCloudApi.IDLEFISH_URL, json, json._head._interface + orderId, CacheMode.REQUEST_FAILED_READ_CACHE);
HttpHelper.http_post(entity, new IdlefishCallback<IdlefishResponse<OrderDetailResponse>, OrderDetailRequest>(true, json) {
@Override
protected void onSuccess(HttpRequest<OrderDetailRequest> httpRequest, boolean isCache, IdlefishResponse<OrderDetailResponse> body, int code) {
super.onSuccess(httpRequest, isCache, body, code);
if (body == null || body._data == null || body._data.data == null) return;
RxBus.send(true, new OrderEvent.DetailChange(body._data.data));
}
});
}
- 页面中接受网络请求
// 接收订单详情
RxBus.observable(OrderEvent.DetailChange.class, this)
.subscribe(detailChange -> {
//do something
});
这样一看,即保证了网络数据的封装,又保证了页面UI和数据的分割,很完美。
其实并不然,这样有一个极大的隐患。由于数据的获取是网络请求,如果在RxBus.send()
触发前,页面已经关闭,那么下次用户进来时,此页面就会获取到上次请求的数据。
RxBus
慎用点
现在我们来总结一些,慎用RxBus
的情况:
- 尽量不要使用sticky事件
- 不要在耗时事件中,使用sticky事件
- 非组件间通信,尽量不要使用其传递数据
- 每个独立的事件,尽量使用不同的Event,防止互相干扰
参考文章:
- https://www.jianshu.com/p/61631134498e
- https://blog.csdn.net/shanshan_1117/article/details/82691218