好的家伙,首先我已经阅读了这篇blog帖子(使用RxJS Observables进行反应性编程的Naive Infinite滚动),并希望在Android上使用RecycleView进行尝试。
这是结果和我的代码......
RESULT
活性
public class MainActivity extends AppCompatActivity {
private final String[] NAME = {"JONG", "MARCH", "BANK", "TAR", "VIJAYA", "JAMES", "OAT", "POOH", "BOW", "NAN"};
private int currentPage = 1;
private RecyclerView rcvInfinite;
private MainAdapter adapter;
private ArrayList<MainListItem> listItems = new ArrayList<>();
private boolean isFetchingApi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rcvInfinite = (RecyclerView) findViewById(R.id.rcvInfinite);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("PAGE", currentPage);
outState.putParcelableArrayList("LISTITEM", listItems);
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
if (savedInstanceState != null) {
currentPage = savedInstanceState.getInt("PAGE", currentPage);
listItems = savedInstanceState.getParcelableArrayList("LISTITEM");
}
if (listItems == null || listItems.isEmpty()) {
listItems = getListItem(currentPage);
++currentPage;
}
adapter = new MainAdapter(this, listItems);
rcvInfinite.setLayoutManager(new LinearLayoutManager(this));
rcvInfinite.setScrollbarFadingEnabled(false);
rcvInfinite.setNestedScrollingEnabled(true);
rcvInfinite.setAdapter(adapter);
ScrollDownPercentageObservable scrollDownPercentageObservable =
new ScrollDownPercentageObservable(rcvInfinite, 70);
Observable.create(scrollDownPercentageObservable)
.filter(scroll70f -> {
if (scroll70f && !isFetchingApi) {
isFetchingApi = true;
return true;
} else {
return false;
}
})
.concatMap(scroll70f -> fetchRemoteData())
.delay(2000, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe((next) -> {
++currentPage;
listItems.addAll(next);
adapter.setItems(listItems);
adapter.notifyDataSetChanged();
isFetchingApi = false;
}, (error) -> {
error.printStackTrace();
}, () -> {
});
}
private Observable<ArrayList<MainListItem>> fetchRemoteData() {
return Observable.create(e -> {
// mock data
ArrayList<MainListItem> listItems1 = getListItem(currentPage);
// emit
e.onNext(listItems1);
e.onComplete();
});
}
@NonNull
private ArrayList<MainListItem> getListItem(int page) {
ArrayList<MainListItem> listItems = new ArrayList<>();
int lastIndex = page * 10;
int firstIndex = lastIndex - (10 - 1);
for (int i = firstIndex; i <= lastIndex; i++) {
listItems.add(new MainListItem(String.format(Locale.getDefault(), "%03d", i), NAME[i % 10]));
}
return listItems;
}
private class ScrollDownPercentageObservable implements ObservableOnSubscribe<Boolean> {
private final RecyclerView mRecycleView;
private final int mPercentage;
private ObservableEmitter<Boolean> emitter;
public ScrollDownPercentageObservable(RecyclerView recycleView, int percentage) {
mRecycleView = recycleView;
mPercentage = percentage;
mRecycleView.addOnScrollListener(onScroll);
}
private RecyclerView.OnScrollListener onScroll = new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView rcv, int dx, int dy) {
super.onScrolled(rcv, dx, dy);
if (emitter != null) {
if (dy > 0) {
// Scrolling up
Log.v("SCROLL", "SCROLL UP");
LinearLayoutManager lm = (LinearLayoutManager) rcv.getLayoutManager();
int pos = lm.findLastVisibleItemPosition();
int itemCount = rcv.getAdapter().getItemCount();
int itemViewedPercentage = (int) ((pos / (float) itemCount) * 100);
emitter.onNext(itemViewedPercentage >= mPercentage);
} else {
// Scrolling down
Log.v("SCROLL", "SCROLL DOWN");
emitter.onNext(false);
}
}
}
};
@Override
public void subscribe(ObservableEmitter<Boolean> e) throws Exception {
emitter = e;
}
}
}
它在结果中显示,但我想知道,是否有任何RxJava方法可以在不使用以下标志的情况下实现相同的结果?
boolean isFetchingApi;
为什么我使用它?
这是因为当onScrolled
满足条件(滚动到70%的项目)时,observable将非常快地发出项目。每页请求api(模拟数据)的结果太多时间。总之,此标志用于停止接收来自onScrolled
的结果流。
任何想法,或者,谢谢。