我尝试使用volley运行2个并行请求以更新数据库(使用DBFlow)。只有在完成两个请求并保存其数据(FK)后,才能填充DB上的一个表。
鉴于以下示例,我希望两个扇区/员工fetch / insert并行运行,然后在插入完成后,保存合同。
/**
* Update the sectors, employees and their contracts
* @return An Observable to watch for the process to complete
*
* sectorsFetch______sectorsInsert________contractsInsert
* employeesFetch____employeesInsert___/
*/
public static Observable<Void> updateEverything() {
try {
Log.d(TAG, "Starting update...");
Observable<JSONArray> employeesFetch = Observable.from(ForumAPI.getInstance().getEmployees());
Observable<List<Contract>> employeesInsert = employeesFetch.flatMap(new Func1<JSONArray, Observable<List<Contract>>>() {
@Override
public Observable<List<Contract>> call(JSONArray employees) {
Log.d(TAG, "Employee list fetched");
return saveEmployees(employees);
}
});
Observable<JSONArray> sectorsFetch = Observable.from(ForumAPI.getInstance().getSectors());
Observable<Void> sectorsInsert = sectorsFetch.flatMap(new Func1<JSONArray, Observable<Void>>() {
@Override
public Observable<Void> call(JSONArray sectors) {
Log.d(TAG, "Sector list fetched");
return saveSectors(sectors);
}
});
return Observable.zip(sectorsInsert, employeesInsert, new Func2<Void, List<Contract>, Void>() {
@Override
public Void call(Void aVoid, List<Contract> contracts) {
Log.d(TAG, "Sectors and employees saved. Saving contracts");
return saveContracts(contracts);
}
});
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, e.getMessage());
return Observable.error(e);
}
}
注意:ForumAPI getEmployees / Sectors返回Future。
Bellow是保存方法。
/**
* Parse and save an array of sectors
* @param jsonSectors The array of sector to save
* @return An Observable to watch for the process to complete.
*/
private static Observable<Void> saveSectors(JSONArray jsonSectors) {
Log.d(TAG, "Transforming JSON sectors to object");
List<Sector> sectList = new ArrayList<>();
try {
for (int i = 0; i < jsonSectors.length(); i++) {
JSONObject jsonSect = jsonSectors.getJSONObject(i);
Sector sect = Sector.build(jsonSect);
sectList.add(sect);
}
Log.d(TAG, sectList.size() + " sectors fetched. Saving...");
ForumDB.getDB().executeTransaction(
FastStoreModelTransaction.insertBuilder(
FlowManager.getModelAdapter(Sector.class)
).addAll(sectList).build());
Log.d(TAG, "Sector list saved");
} catch (JSONException e) {
Log.e(TAG, "Unable to parse sector list. " + e.getMessage());
return Observable.error(e);
}
return Observable.empty();
}
/**
* Parse and save an array of sectors
* @param jsonSectors The array of sector to save
* @return An Observable to watch for the process to complete.
*/
private static Observable<Void> saveSectors(JSONArray jsonSectors) {
Log.d(TAG, "Transforming JSON sectors to object");
List<Sector> sectList = new ArrayList<>();
try {
for (int i = 0; i < jsonSectors.length(); i++) {
JSONObject jsonSect = jsonSectors.getJSONObject(i);
Sector sect = Sector.build(jsonSect);
sectList.add(sect);
}
Log.d(TAG, sectList.size() + " sectors fetched. Saving...");
ForumDB.getDB().executeTransaction(
FastStoreModelTransaction.insertBuilder(
FlowManager.getModelAdapter(Sector.class)
).addAll(sectList).build());
Log.d(TAG, "Sector list saved");
} catch (JSONException e) {
Log.e(TAG, "Unable to parse sector list. " + e.getMessage());
return Observable.error(e);
}
return Observable.empty();
}
/**
* Parse and save an array of employees
* @param jsonEmployees The array of employee to save
* @return An Observable to watch for the process to complete.
*/
private static Observable<List<Contract>> saveEmployees(JSONArray jsonEmployees) {
Log.d(TAG, "Transforming JSON employees to object");
List<Person> empList = new ArrayList<>();
List<Contract> contractList = new ArrayList<>();
try {
for (int i = 0; i < jsonEmployees.length(); i++) {
JSONObject jsonEmp = jsonEmployees.getJSONObject(i);
Person emp = Person.build(jsonEmp);
empList.add(emp);
JSONArray jsonContracts = jsonEmp.getJSONArray("sectors");
for (int j = 0; j < jsonContracts.length(); j++) {
Contract contract = new Contract();
contract.setSectorId(jsonContracts.getJSONObject(j).getInt("id"));
contract.setPersonForumId(emp.getForumId());
contractList.add(contract);
}
}
Log.d(TAG, empList.size() + " employees fetched. Saving...");
ForumDB.getDB().executeTransaction(
FastStoreModelTransaction.insertBuilder(
FlowManager.getModelAdapter(Person.class)
).addAll(empList).build());
Log.d(TAG, "Employee list saved");
} catch (JSONException e) {
Log.e(TAG, "Unable to parse employee list. " + e.getMessage());
return Observable.error(e);
}
return Observable.just(contractList);
}
/**
* Save a list of contract
* @param contracts The list of contract to save
* @return An Observable to watch for the process to complete.
*/
private static Void saveContracts(List contracts) {
ForumDB.getDB().executeTransaction(
FastStoreModelTransaction.insertBuilder(
FlowManager.getModelAdapter(Contract.class)
).addAll(contracts).build());
Log.d(TAG, "Contract list saved");
return null;
}
问题是,当从Android活动订阅该全局observable时,我的观察者onCompleted会在sectorFetch发出数据之后立即被调用(无论是扇区插入还是我的zip都被调用)。
Bellow是日志
D/com.xx.observable.DataUpdater: Starting update...
D/com.xx.helper.ForumAPI: Requesting employee list
D/com.xx.helper.ForumAPI: Request added to queue...
D/com.xx.helper.ForumAPI: Requesting sector list
D/com.xx.helper.ForumAPI: Request added to queue
D/com.xx.observable.DataUpdater: Sector list fetched
D/com.xx.observable.DataUpdater: Transforming JSON sectors to object
D/com.xx.observable.DataUpdater: 8 sectors fetched. Saving...
D/com.xx.observable.DataUpdater: Sector list saved
D/com.xx.activity.Startup: onCompleted reached
我无法找到问题所在。我的一个观察者是否正在发出一些东西,所以我的拉链会在它之前被调用吗?
答案 0 :(得分:2)
1.1.6中的zip
文档已更新,以描述此案例:
操作员按照指定的顺序订阅其来源,并在取消订阅其他来源时,如果其中一个来源比其他来源短,则热切地完成。因此,其他源可能永远无法运行完成(因此不会调用
doOnCompleted()
。如果源的长度完全相同,也可能发生这种情况;如果源A完成且B已被消耗,即将完成,操作员检测到A不会发送更多值,并且会立即取消订阅B.例如:zip(Arrays.asList(range(1, 5).doOnCompleted(action1), range(6, 5).doOnCompleted(action2)), (a) -> a)
action1
将被调用但action2
将不会。 / p>
换句话说,请勿使用empty()
进行压缩。您可以使用Observable.<Void>just(null)
压缩并忽略该轨道。