如何使用RXJava Observables处理用于填充模型的多个请求?
我们在网络堆栈中使用ReactiveX和Retrofit以异步方式处理所有API请求。
我们的目标是创建一个返回完全填充的User
模型集合的方法。 每个User
模型都有一个Pet
对象列表。 我们可以通过一个请求获取所有User
模型。 但是,每个User
需要请求Pet
模型。
获得用户很简单:
// Service.java @GET("users/?locationId={id}") Observable<List> getUsersForLocation(@Path("id") int locationId); @GET("pets/?userId={id}") Observable<List> getPetsForUser(@Path("id") int userId); // DataManager.java public Observable<List> getUsersForLocation(int locationId) { return api.getUsersForLocation(locationId); } public Observable<List> getPetsForUser(int userId) { return api.getPetsForUser(userId); }
我们希望找到一些方便的(RX风格)循环User
列表的方法,为每个用户获取Pet
,将它们分配给User
并最终返回Observable<List>
。
我对RX很新。 我查看了文档,并尝试使用各种方法,如flatMap()
和zip
,但是,我还没有找到变换或组合的确切组合来实现它。
我写了一个小样本应用程序,它可以实现您想要实现的目标。 这里的组件:
public class Datasource { public Observable> users() { return Observable.just(Arrays.asList( new User("1", "Foo"), new User("2", "Bar") )); } public Observable> pets(User user) { return Observable.just(Arrays.asList( new Pet(user.getName() + "'s cat"), new Pet(user.getName() + "'s dog") )); } }
宠物类:
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 + '\'' + '}'; } }
用户类:
public class User { private String mName; private String mId; private List mPetList; public User(String id, String name) { this(id, name, Collections. emptyList()); } public User(String id, String name, List pets) { mName = name; mId = id; mPetList = pets; } public String getName() { return mName; } public String getId() { return mId; } public User copyWithPets(List pets) { return new User(mId, mName, pets); } @Override public String toString() { return "User{" + "mName='" + mName + '\'' + ", mId='" + mId + '\'' + ", mPetList=" + mPetList + '}'; } }
全部放在一起:
datasource.users() .flatMap(new Func1, Observable>() { @Override public Observable call(List users) { return Observable.from(users); } }) .flatMap(new Func1>() { @Override public Observable call(final User user) { return datasource.pets(user) .map(new Func1, User>() { @Override public User call(List pets) { return user.copyWithPets(pets); } }); } }) .toList() .subscribe(new Action1>() { @Override public void call(List
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'}]}
如果它没有回答你的问题,请发布用户和宠物的实际数据模型。