如何使用RXJava Observables处理用于填充模型的多个请求? [英] How can multiple requests used to populate models be handled using RXJava Observables?
问题描述
我们在网络堆栈中使用ReactiveX和Retrofit以异步方式处理所有API请求。
We are using ReactiveX and Retrofit in our network stack to handle all API requests in an asynchronous way.
我们的目标是创建一个方法,返回完全填充的用户
模型集合。每个用户
模型都有一个 Pet
对象的列表。我们可以通过一个请求获取所有用户
模型。但是, Pet
模型需要按用户
进行请求。
Our goal is to create one method that will return a completely populated collection of User
models. Each User
model has a list of Pet
objects. We can fetch all of the User
models with one request. However, Pet
models need to be requested per User
.
获取用户很简单:
// 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风格)循环方式用户
列表,为每个用户获取 Pet
,并将其分配给用户
并最终返回 Observable< List< User>>
。
We would like to find some convenient (RX style) way of looping through the User
list, fetching the Pet
s for that each user, assigning them to the User
and ultimately returning the Observable<List<User>>
.
我很公平RX新手。我查看了文档,并尝试使用各种方法,如 flatMap()
和 zip
,但是,我还没有找到变换或组合器的确切组合来实现它。
I am fairly new to RX. I've looked over the documentation and have tried using various methods such as flatMap()
and zip
, however, I have yet to find the exact combination of transforms or combiners to make it happen.
推荐答案
我写了一个小样本应用程序来实现你想要实现的目标。这里的组件:
I wrote a small sample app that makes what you are trying to achieve. Here the components:
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")
));
}
}
宠物等级:
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<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'}]}
如果它没有回答你的问题,请发布用户和宠物的实际数据模型。
If it doesn't answer you question please post you actual datamodel for User and Pet.
这篇关于如何使用RXJava Observables处理用于填充模型的多个请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!