如何使用RxJava将多个对象转换为一个对象?

时间:2018-10-24 21:06:56

标签: android rx-java rx-java2

我有日历对象,该对象中包含多个不同对象的列表,例如:任务估算工作订单 BlockTime

因此,为了显示所有这些 Calendar 事件,我计划创建具有事件类型的 CalendarItem 对象并添加该事件。

public class CalendarItem {

private int type;
private Task task;
private Estimate estimate;
private WorkOrder workOrder;
private BlockTime blockTime;

public CalendarItem() {
}
}

我有这个RxJava函数:

Disposable disposable = calendarRepository.getCalendar(startDate, endDate)
    .subscribeOn(Schedulers.io())
    .flatMap((Function<Calendar, Publisher<List<CalendarItem>>>) calendar -> {
      List<Task> tasks = calendar.getTasks();
      List<WorkOrder> workOrders = calendar.getWorkOrders();
      List<BlockTime> blockTimes = calendar.getBlockTimes();
      List<Estimate> estimates = calendar.getEstimates();

      List<CalendarItem> calendarItems = new ArrayList<>();

      if(tasks != null) {
        for(Task t : tasks) {
          CalendarItem item = new CalendarItem();
          item.setType(Constants.CALENDAR_TASK);
          item.setTask(t);
          calendarItems.add(item);
        }
      }

      if(workOrders != null) {
        for(WorkOrder w : workOrders) {
          CalendarItem item = new CalendarItem();
          item.setType(Constants.CALENDAR_WORK_ORDER);
          item.setWorkOrder(w);
          calendarItems.add(item);
        }
      }

      if(estimates != null) {
        for(Estimate e : estimates) {
          CalendarItem item = new CalendarItem();
          item.setType(Constants.CALENDAR_ESTIMATE);
          item.setEstimate(e);
          calendarItems.add(item);
        }
      }

      if(blockTimes != null) {
        for(BlockTime b : blockTimes) {
          CalendarItem item = new CalendarItem();
          item.setType(Constants.CALENDAR_BLOCKED_TIME);
          item.setBlockTime(b);
          calendarItems.add(item);
        }
      }

      return Flowable.just(calendarItems);
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(calendarItems -> view.displayCalendar(calendarItems), view::handleError);

如何在 flatMap()运算符中改进代码?

2 个答案:

答案 0 :(得分:1)

如何更改CalendarItem以首先静态创建它?

public class CalendarItem {

    private int type;
    private Task task;
    private Estimate estimate;
    private WorkOrder workOrder;
    private BlockTime blockTime;

    // Change it to private.
    // In the future, we will only create this object through static methods.
    private CalendarItem() {
    }

    public static CalendarItem fromTask(Task t) {
        CalendarItem item = new CalendarItem();
        item.setType(Constants.CALENDAR_TASK);
        item.setTask(t);
        return item;
    }

    public static CalendarItem fromWorkOrder(WorkOrder w) {
        CalendarItem item = new CalendarItem();
        item.setType(Constants.CALENDAR_WORK_ORDER);
        item.setWorkOrder(w);
        return item;
    }

    public static CalendarItem fromEstimate(Estimate e) {
        CalendarItem item = new CalendarItem();
        item.setType(Constants.CALENDAR_ESTIMATE);
        item.setEstimate(e);
        return item;
    }

    public static CalendarItem fromBlockTime(BlockTime b) {
        CalendarItem item = new CalendarItem();
        item.setType(Constants.CALENDAR_BLOCKED_TIME);
        item.setBlockTime(b);
        return item;
    }
    ...
}

如果可以使用Java Optional或Stream,则可以编写更简洁的代码。 (Android上有可用的库,例如Lightweight-Stream-API。)

Disposable disposable = calendarRepository.getCalendar(startDate, endDate)
                .subscribeOn(Schedulers.io())
                .map(calendar -> {
                    List<CalendarItem> calendarItems = new ArrayList<>();

                    // tasks
                    calendarItems.addAll(Optional.ofNullable(calendar.getTasks()).map(it -> it.stream().map(CalendarItem::fromTask).collect(toList())).orElse(emptyList()));

                    // workOrders
                    calendarItems.addAll(Optional.ofNullable(calendar.getWorkOrders()).map(it -> it.stream().map(CalendarItem::fromWorkOrder).collect(toList())).orElse(emptyList()));

                    // estimates
                    calendarItems.addAll(Optional.ofNullable(calendar.getEstimates()).map(it -> it.stream().map(CalendarItem::fromEstimate).collect(toList())).orElse(emptyList()));

                    // blockTimes
                    calendarItems.addAll(Optional.ofNullable(calendar.getBlockTimes()).map(it -> it.stream().map(CalendarItem::fromBlockTime).collect(toList())).orElse(emptyList()));

                    return calendarItems;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(calendarItems -> view.displayCalendar(calendarItems), view::handleError);

如果只想使用RxJava,也可以使用下面的代码。 (看起来有点复杂。)

Disposable disposable = calendarRepository.getCalendar(startDate, endDate)
                .subscribeOn(Schedulers.io())
                .map(calendar -> {
                    List<Task> tasks = calendar.getTasks();
                    List<WorkOrder> workOrders = calendar.getWorkOrders();
                    List<BlockTime> blockTimes = calendar.getBlockTimes();
                    List<Estimate> estimates = calendar.getEstimates();

                    List<CalendarItem> calendarItems = new ArrayList<>();

                    // tasks
                    if (tasks != null) {
                        calendarItems.addAll(
                                Observable.fromIterable(tasks)
                                        .map(CalendarItem::fromTask)
                                        .toList()
                                        .blockingGet()
                        );
                    }

                    // workOrders
                    if (workOrders != null) {
                        calendarItems.addAll(
                                Observable.fromIterable(workOrders)
                                        .map(CalendarItem::fromWorkOrder)
                                        .toList()
                                        .blockingGet()
                        );
                    }

                    // estimates
                    if (blockTimes != null) {
                        calendarItems.addAll(
                                Observable.fromIterable(estimates)
                                        .map(CalendarItem::fromEstimate)
                                        .toList()
                                        .blockingGet()
                        );
                    }

                    // blockTimes
                    if (blockTimes != null) {
                        calendarItems.addAll(
                                Observable.fromIterable(blockTimes)
                                        .map(CalendarItem::fromBlockTime)
                                        .toList()
                                        .blockingGet()
                        );
                    }

                    return calendarItems;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(calendarItems -> view.displayCalendar(calendarItems), view::handleError);

答案 1 :(得分:0)

一种方法是使用更具功能性的样式,如下所示:

.flatMap(calendar -> {
    Observable<CalendarItem> tasks = Observable
        .just(Optional.ofNullable(calendar.getTasks()).orElse(Collections.emptyList()))
        .map(task -> {
            CalendarItem item = new CalendarItem();
            item.setType(Constants.CALENDAR_TASK);
            item.setTask(task);
            return item;
        });

    Observable<CalendarItem> workOrders = Observable
        .just(Optional.ofNullable(calendar.getWorkOrders()).orElse(Collections.emptyList()))
        .map(workOrder -> {
            CalendarItem item = new CalendarItem();
            item.setType(Constants.CALENDAR_WORK_ORDER);
            item.setWorkOrder(task);
            return item;
        });

    // estimates and blockTimes

    return tasks.mergeWith(workOrders).mergeWith(estimates).mergeWith(blockTimes);
});