2016-04-12 28 views
4

我正在用RxJava实现一个事件总线(RxBus)。RxJava作为事件总线,onNext被多次调用时只有一个事件发布

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); 
    } 
} 

邮政从viewHolder一个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)); 
      } 
     }); 
    } 
} 

一个事件从片段

@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); 
       } 
      } 
    ); 
} 
订阅的事件

问题是:当我点击itemViewTagImageButton时,RxBus.post()只被调用一次(这是正确的),但Action1 call()被称为多次(甚至不是常数时间)。请参阅下面的日志。

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] 

我怎样才能让它只调用一次?

编辑:我发现如果Action1 call()这次被调用N次,下次我点击这个项目时它会被调用N + 1次。看起来观察者正在向用户发送历史上随后观察到的所有项目。

+0

您创建了多少'mItemClickSubscription'? – srain

+0

@srain只有一个'mItemClickSubscription'。实际上'mItemClickSubscription'直到'unsubscribe()'才被使用。 –

+0

你创建了多少'Fragment'?你的'unsubscribe()'方法在哪里? – srain

回答

4

最后找到解决方案。

很简单:我应该在onStop()中调用mItemClickSubscription.unsubscribe();mApplyTagSubscription.unsubscribe();

PublishSubject用于事件总线。 PublishSubject是一个主题:

主题是,一旦观察者已经订阅,就将所有随后观察到的项目发送给订户。

所以,如果你不这样做unsubscribe()认购,此次订阅将保持“记录”的所有事件发生在历史上,并放出所有的人都曾经.subscribe(onNext)执行。

+0

太棒了!我在android中遇到同样的问题。感谢分享。 –