Skip to content

Commit 5e9a51a

Browse files
author
Kaushik Gopal
committed
Merge branch 'kg/feat/pagingation_auto'
* kg/feat/pagingation_auto: feat: update README feat: auto paginate the list fix: remove moar btn fix: create pagination auto adapter fix: add project settings + handle progress explicitly in funcsionts fix: block duplicate calls + back pressure protect feat: wip: create new pagination auto fragment ref: move pagination adapter to independent class
2 parents eefa39d + 225ee9a commit 5e9a51a

File tree

6 files changed

+305
-91
lines changed

6 files changed

+305
-91
lines changed

.idea/codeStyleSettings.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ I leverage the simple use of a Subject here. Honestly, if you don't have your it
168168

169169
This example basically sends the page number to a Subject, and the subject handles adding the items. Notice the use of `concatMap` and the return of an `Observable<List>` from `_itemsFromNetworkCall`.
170170

171+
For kicks, I've also included a `PaginationAutoFragment` example, this "auto-paginates" without us requiring to hit a button. It should be simple to follow if you got how the previous example works.
172+
171173
Here are some other fancy implementations (while i enjoyed reading them, i didn't land up using them for my real world app cause personally i don't think it's necessary):
172174

173175
* [Matthias example of an Rx based pager](https://gist.github.com/mttkay/24881a0ce986f6ec4b4d)
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.morihacky.android.rxjava.pagination;
2+
3+
import android.support.v7.widget.RecyclerView;
4+
import android.view.LayoutInflater;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import android.widget.Button;
8+
import android.widget.TextView;
9+
10+
import com.morihacky.android.rxjava.R;
11+
import com.morihacky.android.rxjava.rxbus.RxBus;
12+
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
16+
class PaginationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
17+
18+
private static final int ITEM_LOG = 0;
19+
private static final int ITEM_BTN = 1;
20+
21+
private final List<String> _items = new ArrayList<>();
22+
private final RxBus _bus;
23+
24+
PaginationAdapter(RxBus bus) {
25+
_bus = bus;
26+
}
27+
28+
void addItems(List<String> items) {
29+
_items.addAll(items);
30+
}
31+
32+
@Override
33+
public int getItemViewType(int position) {
34+
if (position == _items.size()) {
35+
return ITEM_BTN;
36+
}
37+
38+
return ITEM_LOG;
39+
}
40+
41+
@Override
42+
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
43+
switch (viewType) {
44+
case ITEM_BTN:
45+
return ItemBtnViewHolder.create(parent);
46+
default:
47+
return ItemLogViewHolder.create(parent);
48+
}
49+
}
50+
51+
@Override
52+
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
53+
switch (getItemViewType(position)) {
54+
case ITEM_LOG:
55+
((ItemLogViewHolder) holder).bindContent(_items.get(position));
56+
return;
57+
case ITEM_BTN:
58+
((ItemBtnViewHolder) holder).bindContent(_bus);
59+
}
60+
}
61+
62+
@Override
63+
public int getItemCount() {
64+
return _items.size() + 1; // add 1 for paging button
65+
}
66+
67+
private static class ItemLogViewHolder extends RecyclerView.ViewHolder {
68+
ItemLogViewHolder(View itemView) {
69+
super(itemView);
70+
}
71+
72+
static ItemLogViewHolder create(ViewGroup parent) {
73+
return new ItemLogViewHolder(LayoutInflater.from(parent.getContext())
74+
.inflate(R.layout.item_log, parent, false));
75+
}
76+
77+
void bindContent(String content) {
78+
((TextView) itemView).setText(content);
79+
}
80+
}
81+
82+
static class ItemBtnViewHolder extends RecyclerView.ViewHolder {
83+
ItemBtnViewHolder(View itemView) {
84+
super(itemView);
85+
}
86+
87+
static ItemBtnViewHolder create(ViewGroup parent) {
88+
return new ItemBtnViewHolder(LayoutInflater.from(parent.getContext())
89+
.inflate(R.layout.item_btn, parent, false));
90+
}
91+
92+
void bindContent(RxBus bus) {
93+
((Button) itemView).setText(R.string.btn_demo_pagination_more);
94+
itemView.setOnClickListener(v -> bus.send(new ItemBtnViewHolder.PageEvent()));
95+
}
96+
97+
static class PageEvent {
98+
}
99+
}
100+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.morihacky.android.rxjava.pagination;
2+
3+
import android.support.v7.widget.RecyclerView;
4+
import android.view.LayoutInflater;
5+
import android.view.View;
6+
import android.view.ViewGroup;
7+
import android.widget.TextView;
8+
import com.morihacky.android.rxjava.R;
9+
import com.morihacky.android.rxjava.rxbus.RxBus;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
13+
class PaginationAutoAdapter
14+
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
15+
16+
private static final int ITEM_LOG = 0;
17+
18+
private final List<String> _items = new ArrayList<>();
19+
private final RxBus _bus;
20+
21+
PaginationAutoAdapter(RxBus bus) {
22+
_bus = bus;
23+
}
24+
25+
@Override
26+
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
27+
return ItemLogViewHolder.create(parent);
28+
}
29+
30+
@Override
31+
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
32+
((ItemLogViewHolder) holder).bindContent(_items.get(position));
33+
34+
boolean lastPositionReached = position == _items.size() - 1;
35+
if (lastPositionReached) {
36+
_bus.send(new PageEvent());
37+
}
38+
}
39+
40+
@Override
41+
public int getItemViewType(int position) {
42+
return ITEM_LOG;
43+
}
44+
45+
@Override
46+
public int getItemCount() {
47+
return _items.size();
48+
}
49+
50+
void addItems(List<String> items) {
51+
_items.addAll(items);
52+
}
53+
54+
private static class ItemLogViewHolder
55+
extends RecyclerView.ViewHolder {
56+
ItemLogViewHolder(View itemView) {
57+
super(itemView);
58+
}
59+
60+
static ItemLogViewHolder create(ViewGroup parent) {
61+
return new ItemLogViewHolder(LayoutInflater.from(parent.getContext())
62+
.inflate(R.layout.item_log, parent, false));
63+
}
64+
65+
void bindContent(String content) {
66+
((TextView) itemView).setText(content);
67+
}
68+
}
69+
70+
static class PageEvent { }
71+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package com.morihacky.android.rxjava.pagination;
2+
3+
import android.os.Bundle;
4+
import android.support.annotation.Nullable;
5+
import android.support.v7.widget.LinearLayoutManager;
6+
import android.support.v7.widget.RecyclerView;
7+
import android.view.LayoutInflater;
8+
import android.view.View;
9+
import android.view.ViewGroup;
10+
import android.widget.ProgressBar;
11+
import butterknife.Bind;
12+
import butterknife.ButterKnife;
13+
import com.morihacky.android.rxjava.MainActivity;
14+
import com.morihacky.android.rxjava.R;
15+
import com.morihacky.android.rxjava.fragments.BaseFragment;
16+
import com.morihacky.android.rxjava.rxbus.RxBus;
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
import java.util.concurrent.TimeUnit;
20+
import rx.Observable;
21+
import rx.Subscription;
22+
import rx.android.schedulers.AndroidSchedulers;
23+
import rx.subjects.PublishSubject;
24+
import rx.subscriptions.CompositeSubscription;
25+
26+
public class PaginationAutoFragment
27+
extends BaseFragment {
28+
29+
@Bind(R.id.list_paging) RecyclerView _pagingList;
30+
@Bind(R.id.progress_paging) ProgressBar _progressBar;
31+
32+
private PaginationAutoAdapter _adapter;
33+
private RxBus _bus;
34+
private PublishSubject<Integer> _paginator;
35+
private boolean _requestUnderWay = false;
36+
private CompositeSubscription _subscriptions;
37+
38+
@Override
39+
public View onCreateView(LayoutInflater inflater,
40+
@Nullable ViewGroup container,
41+
@Nullable Bundle savedInstanceState) {
42+
View layout = inflater.inflate(R.layout.fragment_pagination, container, false);
43+
ButterKnife.bind(this, layout);
44+
return layout;
45+
}
46+
47+
@Override
48+
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
49+
super.onActivityCreated(savedInstanceState);
50+
51+
_bus = ((MainActivity) getActivity()).getRxBusSingleton();
52+
53+
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
54+
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
55+
_pagingList.setLayoutManager(layoutManager);
56+
57+
_adapter = new PaginationAutoAdapter(_bus);
58+
_pagingList.setAdapter(_adapter);
59+
60+
_paginator = PublishSubject.create();
61+
}
62+
63+
@Override
64+
public void onStart() {
65+
super.onStart();
66+
_subscriptions = new CompositeSubscription();
67+
68+
Subscription s2 =//
69+
_paginator.onBackpressureDrop()
70+
.doOnNext(i -> {
71+
_requestUnderWay = true;
72+
_progressBar.setVisibility(View.VISIBLE);
73+
})
74+
.concatMap(this::_itemsFromNetworkCall)
75+
.observeOn(AndroidSchedulers.mainThread())
76+
.map(items -> {
77+
_adapter.addItems(items);
78+
_adapter.notifyDataSetChanged();
79+
return null;
80+
})
81+
.doOnNext(i -> {
82+
_requestUnderWay = false;
83+
_progressBar.setVisibility(View.INVISIBLE);
84+
})
85+
.subscribe();
86+
87+
// I'm using an RxBus purely to hear from a nested button click
88+
// we don't really need Rx for this part. it's just easy ¯\_(ツ)_/¯
89+
Subscription s1 =//
90+
_bus.asObservable()//
91+
.filter(o -> !_requestUnderWay)//
92+
.subscribe(event -> {
93+
if (event instanceof PaginationAutoAdapter.PageEvent) {
94+
95+
// trigger the paginator for the next event
96+
int nextPage = _adapter.getItemCount();
97+
_paginator.onNext(nextPage);
98+
}
99+
});
100+
101+
_subscriptions.add(s1);
102+
_subscriptions.add(s2);
103+
104+
_paginator.onNext(0);
105+
}
106+
107+
@Override
108+
public void onStop() {
109+
super.onStop();
110+
_subscriptions.clear();
111+
}
112+
113+
/**
114+
* Fake Observable that simulates a network call and then sends down a list of items
115+
*/
116+
private Observable<List<String>> _itemsFromNetworkCall(int pageStart) {
117+
return Observable.just(true)//
118+
.observeOn(AndroidSchedulers.mainThread())//
119+
.delay(2, TimeUnit.SECONDS)
120+
.map(dummy -> {
121+
List<String> items = new ArrayList<>();
122+
for (int i = 0; i < 10; i++) {
123+
items.add("Item " + (pageStart + i));
124+
}
125+
return items;
126+
});
127+
}
128+
}

0 commit comments

Comments
 (0)