如何使用 RXJava Observables 处理用于填充模型的多个请求?

How can multiple requests used to populate models be handled using RXJava Observables?

我们在网络堆栈中使用 ReactiveX 和 Retrofit 以异步方式处理所有 API 请求。

我们的目标是创建一种方法,该方法将 return 完全填充的 User 模型集合。每个 User 模型都有一个包含 Pet 个对象的列表。我们可以通过一个请求获取所有 User 模型。但是,每个 User 需要请求 Pet 个模型。

获取用户很简单:

// Service.java
@GET("users/?locationId={id}")
Observable<List<User>> getUsersForLocation(@Path("id") int locationId);

@GET("pets/?userId={id}")
Observable<List<Pet>> getPetsForUser(@Path("id") int userId);

// DataManager.java
public Observable<List<User>> getUsersForLocation(int locationId) {
    return api.getUsersForLocation(locationId);
}

public Observable<List<Pet>> getPetsForUser(int userId) {
    return api.getPetsForUser(userId);
}

我们想找到一些方便的(RX 样式)循环遍历 User 列表的方法,为每个用户获取 Pets,将它们分配给 User并最终 returning Observable<List<User>>.

我对 RX 还很陌生。我查看了文档并尝试使用各种方法,例如 flatMap()zip,但是,我还没有找到转换或组合器的确切组合来实现它。

我写了一个小示例应用程序来实现您想要实现的目标。这里的组件:

public class Datasource {

    public Observable<List<User>> users() {
        return Observable.just(Arrays.asList(
                new User("1", "Foo"), new User("2", "Bar")
        ));
    }

    public Observable<List<Pet>> pets(User user) {
        return Observable.just(Arrays.asList(
                new Pet(user.getName() + "'s cat"),
                new Pet(user.getName() + "'s dog")
        ));
    }
}

宠物class:

public class Pet {
    private String mName;

    public Pet(String name) {
        mName = name;
    }

    public String getName() {
        return mName;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "mName='" + mName + '\'' +
                '}';
    }
}

用户class:

public class User {

    private String mName;
    private String mId;
    private List<Pet> mPetList;

    public User(String id, String name) {
        this(id, name, Collections.<Pet>emptyList());
    }

    public User(String id, String name, List<Pet> pets) {
        mName = name;
        mId = id;
        mPetList = pets;
    }

    public String getName() {
        return mName;
    }

    public String getId() {
        return mId;
    }

    public User copyWithPets(List<Pet> pets) {
        return new User(mId, mName, pets);
    }

    @Override
    public String toString() {
        return "User{" +
                "mName='" + mName + '\'' +
                ", mId='" + mId + '\'' +
                ", mPetList=" + mPetList +
                '}';
    }
}

放在一起:

datasource.users()
        .flatMap(new Func1<List<User>, Observable<User>>() {
            @Override
            public Observable<User> call(List<User> users) {
                return Observable.from(users);
            }
        })
        .flatMap(new Func1<User, Observable<User>>() {
            @Override
            public Observable<User> call(final User user) {
                return datasource.pets(user)
                        .map(new Func1<List<Pet>, User>() {
                            @Override
                            public User call(List<Pet> pets) {
                                return user.copyWithPets(pets);
                            }
                        });
            }
        })
        .toList()
        .subscribe(new Action1<List<User>>() {
            @Override
            public void call(List<User> users) {
                for (User user : users) {
                    Log.d(TAG, "user: " + user.toString());
                }
            }
        });

它产生:

D/MainActivity: user: User{mName='Foo', mId='1', mPetList=[Pet{mName='Foo's cat'}, Pet{mName='Foo's dog'}]}
D/MainActivity: user: User{mName='Bar', mId='2', mPetList=[Pet{mName='Bar's cat'}, Pet{mName='Bar's dog'}]}

如果它不能回答您的问题,请post您是用户和宠物的实际数据模型。