繁体   English   中英

Android RXJava2改造处理分页

[英]Android RXJava2 Retrofit Handling paging

我在处理RXJava2分页时遇到问题。 我尝试遵循SO的这篇文章,但它已过时。 我希望得到一个最新的答案。 我正在使用Retrofit,并尝试分页第三方API,直到获得所有结果为止。 响应如下,但是我非常想浏览所有页面并合并所有结果。

目前,我的代码如下:

public Observable<WatchList> syncWatchlistSection(String accountId) {
    String sessionToken = mLocal.getSessionId();
    int page = 1;

    return getWatchlistFromServerHelper(sessionToken, accountId, page).concatMap(new Function<WatchList, ObservableSource<? extends WatchList>>() {
        @Override
        public ObservableSource<? extends WatchList> apply(WatchList watchList) throws Exception {
            return Observable.fromArray(watchList);
        }
    });

}

并且在同一文件中,帮助程序文件类似于先前的SO帖子。

private Observable<WatchList> getWatchlistFromServerHelper(String sessionToken, String accountId, int page) {
        return mRestAPI.fetchWatchlistOnServer(sessionToken, accountId, page).concatMap(new Function<WatchList, Observable<WatchList>>() {
            @Override
            public Observable<WatchList> apply(WatchList watchList) throws Exception {
                if (watchList.getPage() == watchList.getTotalPages()) {
                    return Observable.just(watchList);
                }
                return Observable.just(watchList).concatWith(getWatchlistFromServerHelper(sessionToken, accountId, page + 1));
            }
        });
    }

我通过订阅我的活动来称呼它。

mSectionLogic.syncWatchlistSection(String.valueOf(account.getId()))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<WatchList>() {
              ... so on ...

这有效,但不处理分页。 响应类似于:

{
  page: 1,
  totalPages: 5,
  results: []
}

我所做的是,它应该在page == totalPages时返回。 除非它不合并先前的结果,而仅返回结果的最后一页。

mRestAPI.fetchWatchlistOnServer是Retrofit2 Get请求,该请求返回Observable<Watchlist>

我究竟做错了什么? 如何将结果与可观察值结合? 最好不要使用Lamda表示法。

我查看过的其他资源:- 具有分页令牌的android rxjava2 / retrofit2链接调用

您需要构建Observable。 您可以使用递归,但是如果您有大量页面,则调用堆栈可能会溢出。 这里查看答案

就像是

private Observable<WatchList> getWatchlistFromServerHelper(String sessionToken, String accountId, int startPage) {
    int index = startPage;
    BehaviorSubject<Integer> pagecontrol = BehaviorSubject.create(startPage);
    Observable<WatchList> ret = pageControl.asObservable()
                                           .concatMap(new Function<Integer,Observable<WatchList>>()
                                                     {
                                                       Observable<WatchList> apply(Integer page) {
                                                            mRestAPI.fetchWatchlistOnServer(sessionToken, accountId, page)
                                                                    .doOnNext(new Function<watchList -> 
                                                                            (watchList.getPage() == watchList.getTotalPages() ? 
                                                                             Observable.<WatchList>empty().doOnCompleted(()->pageControl.onCompleted()) :
                                                                             pageControl.onNext(page+1)));
                                                        }
                                                     }
                                                     );
    return ret;
}

应该管用。

我下面的示例代码正在运行,在这里您需要根据需要进行一些修改。

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ProgressBar;

import org.reactivestreams.Publisher;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.processors.PublishProcessor;

/**
* Created by Akash on 11/11/17.
*/
public class MainActivity extends AppCompatActivity {

private final int VISIBLE_THRESHOLD = 1;
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.progressBar)
ProgressBar progressBar;


private CompositeDisposable mDisposable;
private PublishProcessor<Integer> mPaginator;
private RxPagingAdapter mAdapter;
private boolean isLoading = false;
private int pageNumber = 1;
private int lastVisibleItem, totalItemCount;
private LinearLayoutManager mLayoutManager;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);

    mDisposable = new CompositeDisposable();
    mPaginator = PublishProcessor.create();
    mLayoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(mLayoutManager);
    mAdapter = new RxPagingAdapter();
    recyclerView.setAdapter(mAdapter);

    // register scroll listener
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView,
                               int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            totalItemCount = mLayoutManager.getItemCount();
            lastVisibleItem = mLayoutManager
                    .findLastVisibleItemPosition();
            if (!isLoading
                    && totalItemCount <= (lastVisibleItem + VISIBLE_THRESHOLD)) {
                pageNumber++;
                mPaginator.onNext(pageNumber);
                isLoading = true;
            }
        }
    });
    subscribeApi();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (!mDisposable.isDisposed())
        mDisposable.dispose();
}

/**
 * Adding to disposable.
 */
private void subscribeApi() {

    mDisposable.add(mPaginator
            .onBackpressureDrop()
            .concatMap(new Function<Integer, Publisher<List<String>>>() {
                @Override
                public Publisher<List<String>> apply(@NonNull Integer page) throws Exception {
                    isLoading = true;
                    progressBar.setVisibility(View.VISIBLE);
                    return apiResponse(page);
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<List<String>>() {
                @Override
                public void accept(@NonNull List<String> items) throws Exception {
                    mAdapter.addItems(items);
                    mAdapter.notifyDataSetChanged();
                    isLoading = false;
                    progressBar.setVisibility(View.INVISIBLE);
                }
            }));

    mPaginator.onNext(pageNumber);

}

/**
 * This is just sample.
 * You can call api with retrofit interface method which returns Flowable and there you go.
 */
private Flowable<List<String>> apiResponse(final int page) {
    return Flowable.just(true)
            .delay(3, TimeUnit.SECONDS)
            .map(new Function<Boolean, List<String>>() {
                @Override
                public List<String> apply(@NonNull Boolean value) throws Exception {
                    List<String> items = new ArrayList<>();
                    for (int i = 1; i <= 10; i++) {
                        items.add("Item " + (page * 10 + i));
                    }
                    return items;
                }
            });
}
}

适配器类方法

 void addItems(List<String> items) {
    this.itemArrayList.addAll(items);
 }

来源:GitHub

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM