【发布时间】:2016-04-12 07:40:04
【问题描述】:
我正在使用 RxJava 实现事件总线 (RxBus)。
RxBus.java
public class RxBus {
private static final String TAG = LogUtils.makeTag(RxBus.class);
private static final RxBus INSTANCE = new RxBus();
private final Subject<Object, Object> mBusSubject = new SerializedSubject<>(PublishSubject.create());
public static RxBus getInstance() {
return INSTANCE;
}
public <T> Subscription register(final Class<T> eventClass, Action1<T> onNext) {
return mBusSubject
.filter(new Func1<Object, Boolean>() {
@Override
public Boolean call(Object event) {
return event.getClass().equals(eventClass);
}
})
// .filter(event -> event.getClass().equals(eventClass))
.map(new Func1<Object, T>() {
@Override
public T call(Object obj) {
return (T) obj;
}
})
// .map(obj -> (T) obj)
.subscribe(onNext);
}
public void post(Object event) {
Log.d(TAG, "Apr12, " + "post event: " + event);
mBusSubject.onNext(event);
}
}
从 RecyclerView 的 viewHolder 发布事件
public ViewHolder(LayoutInflater inflater, final ViewGroup parent) {
super(inflater.inflate(R.layout.bill_card, parent, false));
drawee = (SimpleDraweeView) itemView.findViewById(R.id.card_image);
title = (TextView) itemView.findViewById(R.id.card_title);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Apr12, item clicked.");
RxBus.getInstance().post(new ItemSelectedEvent(position));
}
});
TagImageButton = (ImageButton) itemView.findViewById(R.id.tag_button);
TagImageButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Log.d(TAG, "Tag button clicked.");
RxBus.getInstance().post(new ApplyTagForItemEvent(position));
}
});
}
}
从 Fragment 订阅事件
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mActivity = getActivity();
Log.d(TAG, "getActivity(): " + getActivity());
mItemClickSubscription = RxBus.getInstance().register(ItemSelectedEvent.class,
new Action1<ItemSelectedEvent>() {
@Override
public void call(ItemSelectedEvent event) {
Log.d(TAG, "Apr12, " + "call event: " + event);
if (mDetail == null) {
if (getParentFragment() instanceof IFragmentStackHolder) {
IFragmentStackHolder fsh = (IFragmentStackHolder) getParentFragment();
Fragment details = new DetailCardFragment();
Bundle args = new Bundle();
args.putInt(ContentHolder.INDEX, event.getPosition());
details.setArguments(args);
fsh.pushFragment(details, event.getPairs());
}
}
}
});
mApplyTagSubscription = RxBus.getInstance().register(ApplyTagForItemEvent.class,
new Action1<ApplyTagForItemEvent>() {
@Override
public void call(ApplyTagForItemEvent event) {
IFragmentStackHolder fsh = (IFragmentStackHolder) getParentFragment();
Fragment tagApplyFragment = new TagApplyFragment();
Bundle args = new Bundle();
args.putInt(ContentHolder.INDEX, event.getPosition());
tagApplyFragment.setArguments(args);
fsh.pushFragment(tagApplyFragment, null);
}
}
);
}
问题是:当我点击itemView 或TagImageButton 时,RxBus.post() 只被调用一次(这是正确的),但Action1 call() 被调用多次(甚至不是恒定时间)。请参阅下面的日志。
D/**-CardContentView(31177): Apr12, item clicked.
D/**-RxBus(31177): Apr12, post event: com.*****.events.ItemSelectedEvent@1a11346e
D/**-CardDetailFragment(31177): Apr12, call event: com.*****.events.ItemSelectedEvent@1a11346e
D/**-CardDetailFragment(31177): Apr12, call event: com.*****.events.ItemSelectedEvent@1a11346e
D/**-CardDetailFragment(31177): Apr12, call event: com.*****.events.ItemSelectedEvent@1a11346e
我怎样才能让它只调用一次?
编辑:我发现如果Action1 call()这次被调用了N次,下次点击item的时候会被调用N+1次。似乎 observable 正在向订阅者发送历史中所有后续观察到的项目。
【问题讨论】:
-
你创建了多少
mItemClickSubscription? -
@srain 只有一个
mItemClickSubscription。实际上mItemClickSubscription直到unsubscribe()才被使用。 -
你创建了多少个
Fragment?你的unsubscribe()方法在哪里? -
@srain 到目前为止,只有这个片段订阅了这个事件。我还没有打电话给
unsubscribe()。我打算在onDestroy()或onStop()中做unsubscribe(),但我认为它对我得到的错误没有影响。 -
@srain 天哪……这正是问题所在。我需要在
onStop()中调用unsubscribe(),这样之前处理的事件就不会再次发出。谢谢你的提示!
标签: android rx-java rx-android event-bus