优化改造请求以防止滞后
Optimizing Retrofit Request To Prevent Lagging
当用户登录到我的应用程序时,我会进行大量轮询。目前,我们没有太多 payload。但是,有效负载 目前每天增长 100 个。这使我们每个用户拥有大约 300 条记录。这是第一周。因此,我们开始 优化 接下来的 千 。 API修改的很好,但是Android应用不稳定
我有一个请求,其中用户目前最多有两个 Territories,我需要获取每个中的所有 Items 领土。所以,我这样做了:
/**
* This is to get all user territories and for each and every territory, fetch all items there;
*/
private Observable<ItemListResponse> getAlltemIByTerritory() {
List<String> territories = PrefUtils.getUserTerritories(context);
return Observable.from(territories).flatMap(territory -> fetchAllTerritoryItemPaged(territory, 1));
}
/**
* This is to fetch all items in a passed territory. There's a per_page of 21.
*/
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
Log.e(TAG, "Each territory page: " + page);
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), page, 21, territory)
.flatMap(itemListResponse -> {
Meta meta = itemListResponse.getBakeResponse().getMeta();
Observable<ItemListResponse> thisPage = Observable.just(itemListResponse);
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
Observable<ItemListResponse> nextPage = fetchAllTerritoryItemPaged(territory, page + 1);
return thisPage.concatWith(nextPage);
} else {
return thisPage;
}
});
}
利用 Observable
public void getAlltemIByTerritory(APIRequestListener apiRequestListener) {
realm.executeTransaction(realm1 -> realm1.where(RealmItem.class).findAll().deleteAllFromRealm());
getAlltemIByTerritory()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ItemListResponse>() {
@Override
public void onCompleted() {
Log.e(TAG, "Completed Item");
apiRequestListener.didComplete(WhichSync.ITEM);
unsubscribe();
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
handleError(e, apiRequestListener, WhichSync.ITEM);
unsubscribe();
}
@Override
public void onNext(ItemListResponse itemListResponse) {
Log.e(TAG, "In the handler next " + itemListResponse.toString());
realm.executeTransaction(realm1 -> {
for (Item itemData : itemListResponse.getItemResponse().getData()) {
RealmItem realmItem = realm1.where(RealmItem.class).equalTo("id", itemData.getId()).findFirst();
if (realmItem != null)
realmItem.deleteFromRealm();
realm1.copyToRealm(Item.copyBakeryToRealm(itemData));
}
});
apiRequestListener.onProgress(itemListResponse.getItemResponse().getMeta(), itemListResponse.getItemResponse().getData().size(), WhichSync.ITEM);
}
});
}
Log.e(TAG, "Each territory page: " + page);
这一行和这一行 Log.e(TAG, "In the handler next " + itemListResponse.toString());
对于 1780 条记录读为 23。有 21 条记录 per_page。然后,第二行停止显示。然后,视图已挂起。然后,当第一个完成后,我会看到第二个随即吐出日志。
这很好用,只是当记录超过 700 条时(第一次尝试使用 1780 条记录),UI 有很大的延迟。在大多数 pre-lollipops
上,它会与 NoClassDefined Exception
一起崩溃,但有时它会起作用。但是,延迟仍然存在。
任何关于优化代码的帮助,谢谢。
Tail Recursion
这里:
/**
* This is to fetch all items in a passed territory. There's a per_page of 21.
*/
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
Log.e(TAG, "Each territory page: " + page);
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), page, 21, territory)
.flatMap(itemListResponse -> {
Meta meta = itemListResponse.getItemResponse().getMeta();
Observable<ItemListResponse> thisPage = Observable.just(itemListResponse);
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
Observable<ItemListResponse> nextPage = fetchAllTerritoryItemPaged(territory, page + 1);
return thisPage.concatWith(nextPage);
} else {
return thisPage;
}
});
}
是导致问题的原因。幸运的是,Rx 为我们提供了 BehaviorSubject
.
所以,我做了类似的事情
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
BehaviorSubject<Integer> pageControl = BehaviorSubject.create(page);
Observable<ItemListResponse> ret = pageControl.asObservable().concatMap(integer -> {
if (integer > 0) {
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), integer, 21, territory)
.doOnNext(itemListResponse -> {
Meta meta = itemListResponse.getItemResponse().getMeta();
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
pageControl.onNext(integer + 1);
} else {
pageControl.onNext(-1);
}
});
} else {
return Observable.<ItemListResponse>empty().doOnCompleted(pageControl::onCompleted);
}
});
return Observable.defer(() -> ret);
}
这不仅消除了延迟,而且请求进来的速度也非常快
当用户登录到我的应用程序时,我会进行大量轮询。目前,我们没有太多 payload。但是,有效负载 目前每天增长 100 个。这使我们每个用户拥有大约 300 条记录。这是第一周。因此,我们开始 优化 接下来的 千 。 API修改的很好,但是Android应用不稳定
我有一个请求,其中用户目前最多有两个 Territories,我需要获取每个中的所有 Items 领土。所以,我这样做了:
/**
* This is to get all user territories and for each and every territory, fetch all items there;
*/
private Observable<ItemListResponse> getAlltemIByTerritory() {
List<String> territories = PrefUtils.getUserTerritories(context);
return Observable.from(territories).flatMap(territory -> fetchAllTerritoryItemPaged(territory, 1));
}
/**
* This is to fetch all items in a passed territory. There's a per_page of 21.
*/
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
Log.e(TAG, "Each territory page: " + page);
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), page, 21, territory)
.flatMap(itemListResponse -> {
Meta meta = itemListResponse.getBakeResponse().getMeta();
Observable<ItemListResponse> thisPage = Observable.just(itemListResponse);
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
Observable<ItemListResponse> nextPage = fetchAllTerritoryItemPaged(territory, page + 1);
return thisPage.concatWith(nextPage);
} else {
return thisPage;
}
});
}
利用 Observable
public void getAlltemIByTerritory(APIRequestListener apiRequestListener) {
realm.executeTransaction(realm1 -> realm1.where(RealmItem.class).findAll().deleteAllFromRealm());
getAlltemIByTerritory()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<ItemListResponse>() {
@Override
public void onCompleted() {
Log.e(TAG, "Completed Item");
apiRequestListener.didComplete(WhichSync.ITEM);
unsubscribe();
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
handleError(e, apiRequestListener, WhichSync.ITEM);
unsubscribe();
}
@Override
public void onNext(ItemListResponse itemListResponse) {
Log.e(TAG, "In the handler next " + itemListResponse.toString());
realm.executeTransaction(realm1 -> {
for (Item itemData : itemListResponse.getItemResponse().getData()) {
RealmItem realmItem = realm1.where(RealmItem.class).equalTo("id", itemData.getId()).findFirst();
if (realmItem != null)
realmItem.deleteFromRealm();
realm1.copyToRealm(Item.copyBakeryToRealm(itemData));
}
});
apiRequestListener.onProgress(itemListResponse.getItemResponse().getMeta(), itemListResponse.getItemResponse().getData().size(), WhichSync.ITEM);
}
});
}
Log.e(TAG, "Each territory page: " + page);
这一行和这一行 Log.e(TAG, "In the handler next " + itemListResponse.toString());
对于 1780 条记录读为 23。有 21 条记录 per_page。然后,第二行停止显示。然后,视图已挂起。然后,当第一个完成后,我会看到第二个随即吐出日志。
这很好用,只是当记录超过 700 条时(第一次尝试使用 1780 条记录),UI 有很大的延迟。在大多数 pre-lollipops
上,它会与 NoClassDefined Exception
一起崩溃,但有时它会起作用。但是,延迟仍然存在。
任何关于优化代码的帮助,谢谢。
Tail Recursion
这里:
/**
* This is to fetch all items in a passed territory. There's a per_page of 21.
*/
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
Log.e(TAG, "Each territory page: " + page);
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), page, 21, territory)
.flatMap(itemListResponse -> {
Meta meta = itemListResponse.getItemResponse().getMeta();
Observable<ItemListResponse> thisPage = Observable.just(itemListResponse);
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
Observable<ItemListResponse> nextPage = fetchAllTerritoryItemPaged(territory, page + 1);
return thisPage.concatWith(nextPage);
} else {
return thisPage;
}
});
}
是导致问题的原因。幸运的是,Rx 为我们提供了 BehaviorSubject
.
所以,我做了类似的事情
private Observable<ItemListResponse> fetchAllTerritoryItemPaged(String territory, int page) {
BehaviorSubject<Integer> pageControl = BehaviorSubject.create(page);
Observable<ItemListResponse> ret = pageControl.asObservable().concatMap(integer -> {
if (integer > 0) {
return itemAPI.getIems("Bearer " + PrefUtils.getToken(context), integer, 21, territory)
.doOnNext(itemListResponse -> {
Meta meta = itemListResponse.getItemResponse().getMeta();
if (meta.getPage() != meta.getPageCount() && meta.getPageCount() > 0) {
pageControl.onNext(integer + 1);
} else {
pageControl.onNext(-1);
}
});
} else {
return Observable.<ItemListResponse>empty().doOnCompleted(pageControl::onCompleted);
}
});
return Observable.defer(() -> ret);
}
这不仅消除了延迟,而且请求进来的速度也非常快