Ich implementiere einen Event-Bus (RxBus) mit RxJava.RxJava als Event-Bus, onNext wird mehrmals aufgerufen, wenn nur ein Event-Post
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);
}
}
Eine Veranstaltung von viewHolder eines RecyclerView
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));
}
});
}
}
die Ereignisse von Fragment Abonnieren
@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);
}
}
);
}
Das Problem ist: Wenn ich auf itemView
oder TagImageButton
klicke, wird RxBus.post()
nur einmal aufgerufen (was korrekt ist), aber Action1 call()
wird mehrmals aufgerufen (nicht einmal konstante Zeiten). Bitte beachten Sie das Protokoll unten.
D/**-CardContentView(31177): Apr12, item clicked.
D/**-RxBus(31177): Apr12, post event: com.*****[email protected]
D/**-CardDetailFragment(31177): Apr12, call event: com.*****[email protected]
D/**-CardDetailFragment(31177): Apr12, call event: com.*****[email protected]
D/**-CardDetailFragment(31177): Apr12, call event: com.*****[email protected]
Wie kann ich es nur einmal aufrufen?
EDIT: Ich fand, dass, wenn Action1 call()
N mal dieses Mal aufgerufen wird, wird es N + 1 mal beim nächsten Mal aufgerufen werden, wenn ich auf dem Artikel klicken. Es scheint, dass das Observable alle nachfolgend beobachteten Elemente in der Geschichte an den Abonnenten aussendet.
Wie viele 'mItemClickSubscription' haben Sie erstellt? – srain
@srain nur ein 'mItemClickSubscription'. Eigentlich wird "mItemClickSubscription" erst verwendet, wenn "unsubscribe()" beendet wird. –
Wie viele 'Fragmente' hast du erstellt? Wo ist deine 'unsubscribe()' Methode? – srain