如何使用 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
列表的方法,为每个用户获取 Pet
s,将它们分配给 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您是用户和宠物的实际数据模型。
我们在网络堆栈中使用 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
列表的方法,为每个用户获取 Pet
s,将它们分配给 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您是用户和宠物的实际数据模型。