优化改造请求以防止滞后

时间:2016-10-15 09:50:57

标签: android rx-java retrofit2 rx-android

当用户登录我的应用时,我会进行大量轮询。目前,我们没有太多有效负载。但是,有效载荷目前正在每天增加100个。这使我们每个用户拥有大约300条记录。这是第一周。因此,我们为下一个数千开始优化 API 已得到很好的修改,但Android应用程序不稳定。

我有一个请求,用户目前最多有两个 Territories ,我需要获取每个 Territory 中的所有 。所以,我这样做了:

/**
* 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());读取23以获得1780条记录。每页有21条记录。然后,第二行停止显示。然后,视图已挂起。然后,当第一个完成后,我会看到之后的第二个吐出日志。

这种方法很好,只是当记录超过700(第一次尝试是1780记录)时,UI上存在巨大的延迟。主要是pre-lollipops,它会与NoClassDefined Exception崩溃,有时会有效。但是,滞后仍然存在。

优化代码的任何帮助,谢谢。

1 个答案:

答案 0 :(得分:0)

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);
}

这不仅可以消除延迟,而且还可以快速提出请求