RxJava2(Android):PublishSubject仅发出一次活动?

时间:2019-04-26 13:29:19

标签: android rx-java rx-java2

发布到PublishSubject时,在我的程序中仅发布第一个发布的对象。我的程序的一些上下文:

我有SomeActivity,还有一个RecyclerView。在我的Recycler.ViewHolder中,我点击了。在onclick方法中,我将一个对象发布到PublishSubject。

在SomeActivity中,我订阅了onCreate中的PublishSubject。运行我的应用程序时,我可以看到SomeActivity仅接收到第一个发布的对象。 PublishSubject包装在一个简单的自定义“ RxBus”中,用于在我的应用程序中不同组件之间进行通信(而不是使用接口等)。

以下是我在视图库中的发布方式:

@Override
public void onClick(View v) {
    RxBus.publish(RxBus.GAME_TOUCHED, new GameEvent(data));
}

这是我在SomeActivity中订阅的方式:

RxBus.subscribe(RxBus.GAME_TOUCHED, this, o -> {
        GameEvent gameEvent = (GameEvent) o;
        //Do something here...
    });

这是我的“ RxBus”:

public final class RxBus {

    private static RxBus INSTANCE;
    private static SparseArray<PublishSubject<Object>> subjectMap = new SparseArray<>();
    private static Map<Object, CompositeDisposable> subscriptionsMap = new HashMap<>();

    public static final int GAME_TOUCHED = 7;

    @Retention(SOURCE)
    @IntDef({GAME_TOUCHED})
    @interface Subject {
    }

    private RxBus() {
    }

    public static synchronized RxBus get() {
        if (INSTANCE == null) {
            INSTANCE = new RxBus();
        }
        return INSTANCE;
    }

    @NonNull
    private static PublishSubject<Object> getSubject(@Subject int subjectCode) {
        PublishSubject<Object> subject = subjectMap.get(subjectCode);
        if (subject == null) {
            subject = PublishSubject.create();
            subject.subscribeOn(AndroidSchedulers.mainThread());
            subjectMap.put(subjectCode, subject);
        }

        return subject;
    }

    @NonNull
    private static CompositeDisposable getCompositeDisposable(@NonNull Object object) {
        CompositeDisposable compositeDisposable = subscriptionsMap.get(object);
        if (compositeDisposable == null) {
            compositeDisposable = new CompositeDisposable();
            subscriptionsMap.put(object, compositeDisposable);
        }

        return compositeDisposable;
    }

    public static void subscribe(@Subject int subject, @NonNull Object lifecycle, @NonNull Consumer<Object> action) {
        Disposable disposable = getSubject(subject).subscribe(action);
        getCompositeDisposable(lifecycle).add(disposable);
    }

    public static void unregister(@NonNull Object lifecycle) {
        CompositeDisposable compositeDisposable = subscriptionsMap.remove(lifecycle);
        if (compositeDisposable != null) {
            compositeDisposable.dispose();
        }
    }

    public static void publish(@Subject int subject, @NonNull Object message) {
        getSubject(subject).onNext(message);
    }

}

简而言之,订阅只为该活动接收/发送一次的某个“ eventype”。

有什么建议吗?

编辑:

public class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {

    private final List<Game> games = new ArrayList<>();
    private final Context context;

    public QuestionAdapter(Context context) {
        this.context = context;
    }

    @NonNull
    @Override
    public QuestionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        QuestionHolder questionHolder = new QuestionHolder(R.layout.layout_item_question, parent);
        return questionHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull QuestionHolder holder, int position) {
        holder.bind(games.get(position));
    }

    @Override
    public int getItemCount() {
        return games.size();
    }

    public void setData(List<Game> newGames){
        games.clear();
        games.addAll(newGames);
        notifyDataSetChanged();
    }

    public void deleteItem(int position) {
        RxBus.publish(RxBus.DELETE_GAME, new GameEvent(games.get(position)));
        notifyDataSetChanged(); //restore view if not/after deleted
    }

    public Context getContext(){
        return context;
    }

}

编辑2:

RxBus.subscribe(RxBus.DELETE_GAME, this, o -> {
            GameEvent gameEvent = (GameEvent) o;
            Game game = gameEvent.getGame();
            MaterialDialog.Builder builder = CustomMaterialDialog.areYouSure("Delete game?", this)
                    .onNegative((dialog, which) -> dialog.dismiss())
                    .onPositive((dialog, which) -> {
                        dialog.dismiss();
                        viewModel.deleteGame(game);
                    });
            showCustomDialog(builder);
        });

编辑3:

适配器的更改:

@Override
public void onBindViewHolder(@NonNull QuestionHolder holder, int position) {
    holder.bind(games.get(position));
    holder.getItemView().setOnClickListener(v -> {
        Game game = holder.getData();
        RxBus.publish(RxBus.GAME_TOUCHED, new GameEvent(game));
    });
}

并将其添加到观看者中:

public View getItemView(){
    return itemView;
}

0 个答案:

没有答案