I have an api which contains 10 data per page , now i want to load the other 10 data of next page while i scroll down the recycler view but i am having some issues while loading the next page data, next page data doesn't load,it would be great if I could get some help.
My EndlessScroll java code:
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 10;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
RecyclerView.LayoutManager mLayoutManager;
public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
}
public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScrolled(RecyclerView view, int dx, int dy) {
int lastVisibleItemPosition = 0;
int totalItemCount = mLayoutManager.getItemCount();
if (mLayoutManager instanceof StaggeredGridLayoutManager) {
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
// get maximum element within the list
lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
} else if (mLayoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
}
else if (mLayoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}
// Call this method whenever performing new searches
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
}
My fragment where i want to use endless recycler view:
public class BlankFragment extends DialogFragment {
public Session session;
private RecyclerView categoryRecyclerView, property_recycler;
private PropertyAdapter propertyAdapter;
private EndlessRecyclerViewScrollListener scrollListener;
private ApiInterface apiInterface;
private Datum datum;
private String next_page_url = null;
public BlankFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_blank, container, false);
apiInterface = ApiClient.getClient().create(ApiInterface.class);
property_recycler = view.findViewById(R.id.viewAllHotRc);
final RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
property_recycler.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
property_recycler.setHasFixedSize(true);
property_recycler.setItemAnimator(new DefaultItemAnimator());
scrollListener = new EndlessRecyclerViewScrollListener((LinearLayoutManager) mLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
if (next_page_url != null) {
getNextPageData(next_page_url);
next_page_url = null;
}
}
};
property_recycler.addOnScrollListener(scrollListener);
session = new Session(getContext());
Call<Datum> propertyCall = apiInterface.getAllProp(session.getAccessToken());
propertyCall.enqueue(new Callback<Datum>() {
#Override
public void onResponse(Call<Datum> call, Response<Datum> response) {
if (response.code() == 200) {
datum = response.body();
final List<Property> propertyList = datum.getPropertyList();
propertyAdapter = new PropertyAdapter(propertyList, getContext());
property_recycler.setAdapter(propertyAdapter);
String pagingObject = datum.getNextPageUrl();
Log.d(TAG, "onResponse: "+pagingObject);
if (pagingObject != null) {
next_page_url = pagingObject;
Log.d(TAG, "NEXTPAGE: "+next_page_url);
} else if (pagingObject== null) {
next_page_url = null;
}
}
}
#Override
public void onFailure(Call<Datum> call, Throwable t) {
if (!call.isCanceled()) {
t.printStackTrace();
}
}
});
return view;
}
void getNextPageData(String nextUrl) {
Call<Datum> callNextPageData = apiInterface.getNxt(session.getAccessToken());
callNextPageData.enqueue(new Callback<Datum>() {
#Override
public void onResponse(Call<Datum> call, Response<Datum> response) {
datum = response.body();
final List<Property> propertyList = datum.getPropertyList();
propertyAdapter = new PropertyAdapter(propertyList, getContext());
property_recycler.setAdapter(propertyAdapter);
String pagingObject = datum.getNextPageUrl();
Log.d(TAG, "onResponse: "+pagingObject);
if (pagingObject== null) {
// getNextPageData(pagingObject.getString("next"));
next_page_url = pagingObject;
} else if (pagingObject == null) {
next_page_url = null;
}
}
#Override
public void onFailure(Call<Datum> call, Throwable t) {
}
});
}
My Api Modle:
public class Datum {
#SerializedName("current_page")
#Expose
private int currentPage;
#SerializedName("data")
#Expose
private List<Property> propertyList = null;
#SerializedName("first_page_url")
#Expose
private String firstPageUrl;
#SerializedName("from")
#Expose
private int from;
#SerializedName("next_page_url")
#Expose
private String nextPageUrl;
#SerializedName("path")
#Expose
private String path;
#SerializedName("per_page")
#Expose
private int perPage;
#SerializedName("prev_page_url")
#Expose
private String prevPageUrl;
#SerializedName("to")
#Expose
private int to;
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public List<Property> getPropertyList() {
return propertyList;
}
public void setPropertyList(List<Property> propertyList) {
this.propertyList = propertyList;
}
public String getFirstPageUrl() {
return firstPageUrl;
}
public void setFirstPageUrl(String firstPageUrl) {
this.firstPageUrl = firstPageUrl;
}
public int getFrom() {
return from;
}
public void setFrom(int from) {
this.from = from;
}
public String getNextPageUrl() {
return nextPageUrl;
}
public void setNextPageUrl(String nextPageUrl) {
this.nextPageUrl = nextPageUrl;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getPerPage() {
return perPage;
}
public void setPerPage(int perPage) {
this.perPage = perPage;
}
public String getPrevPageUrl() {
return prevPageUrl;
}
public void setPrevPageUrl(String prevPageUrl) {
this.prevPageUrl = prevPageUrl;
}
My Interface:
#GET("/api/properties")
Call getAllProp(#Header("Authorization") String token);
#GET("/api/properties")
Call getNxt(#Header("Authorization") String token);
Related
I have 24 rows in database from 1 to 24 but the problem with EndlessRecyclerViewScrollListener class when I try show Items on recyclerview become shuffle items.
I want show Items from #1 to #24
PostsActivity
public class PostsActivity extends AppCompatActivity {
#BindView(R.id.rv_posts)
RecyclerView rv_posts;
SaveSystem saveSystem;
List<PostsModels> postsModels = new ArrayList<>();
PostsAdapter postsAdapter;
EndlessRecyclerViewScrollListener scrollListener;
int page = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
ButterKnife.bind(this);
saveSystem = new SaveSystem(this);
//check first time
if (saveSystem.LoadBooleanData("FirstTime")) {
saveSystem.SaveStringData("language", "en");
saveSystem.SaveBooleanData("FirstTime", false);
}
//setData
setData();
}
void setData() {
postsAdapter = new PostsAdapter(PostsActivity.this, postsModels);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(PostsActivity.this, LinearLayoutManager.VERTICAL, false);
rv_posts.setLayoutManager(linearLayoutManager);
rv_posts.setAdapter(postsAdapter);
scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int i, int totalItemsCount, RecyclerView view) {
page = page + 10;
Toast.makeText(PostsActivity.this, "" + page, Toast.LENGTH_SHORT).show();
retrofit(page);
}
};
rv_posts.addOnScrollListener(scrollListener);
retrofit(page);
}
void retrofit(int number) {
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://***").addConverterFactory(GsonConverterFactory.create()).build();
HTTP http = retrofit.create(HTTP.class);
Call<List<PostsModels>> call = http.get_posts(saveSystem.LoadStringData("language"), number);
call.enqueue(new Callback<List<PostsModels>>() {
#Override
public void onResponse(Call<List<PostsModels>> call, Response<List<PostsModels>> response) {
List<PostsModels> list = response.body();
for (PostsModels i : list) {
postsModels.add(new PostsModels(i.id, i.user_id, i.user_name, i.word, i.description, i.sound, i.level, i.shortcut));
}
postsAdapter.notifyItemRangeInserted(postsAdapter.getItemCount(), list.size() - 1);
}
#Override
public void onFailure(Call<List<PostsModels>> call, Throwable t) {
}
});
}
}
PostsModels
public class PostsModels {
#SerializedName("id")
String id;
#SerializedName("user_id")
String user_id;
#SerializedName("user_name")
String user_name;
#SerializedName("word")
String word;
#SerializedName("description")
String description;
#SerializedName("sound")
String sound;
#SerializedName("level")
String level;
#SerializedName("shortcut")
String shortcut;
public PostsModels(String id, String user_id, String user_name, String word, String description, String sound, String level, String shortcut) {
this.id = id;
this.user_id = user_id;
this.user_name = user_name;
this.word = word;
this.description = description;
this.sound = sound;
this.level = level;
this.shortcut = shortcut;
}
}
PostsAdapter
public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.posts> {
Context context;
List<PostsModels> postsModels;
int lastCheckedPosition = -1;
public PostsAdapter(Context context, List<PostsModels> postsModels) {
this.context = context;
this.postsModels = postsModels;
}
#NonNull
#Override
public posts onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_posts, viewGroup, false);
posts viewHolder = new posts(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull posts posts, int i) {
PostsModels list = postsModels.get(i);
//set photo
Picasso.get().load("http://graph.facebook.com/" + list.user_id + "/picture?type=large").into(posts.img_profile);
//set word
posts.txt_word.setText(list.word);
//set id
posts.txt_id.setText("#" + list.id);
//set description
posts.txt_description.setText(list.description);
//if checked
if (lastCheckedPosition == i) {
posts.linear_layout.setBackgroundColor(context.getResources().getColor(R.color.posts_item_selected_1));
posts.frame_pink.setVisibility(View.VISIBLE);
} else {
posts.linear_layout.setBackgroundColor(0x000000000);
posts.frame_pink.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return postsModels.size();
}
class posts extends RecyclerView.ViewHolder {
#BindView(R.id.linear_layout)
LinearLayout linear_layout;
#BindView(R.id.frame_pink)
FrameLayout frame_pink;
#BindView(R.id.img_profile)
CircleImageView img_profile;
#BindView(R.id.txt_word)
TextViewFont txt_word;
#BindView(R.id.txt_id)
TextViewFont txt_id;
#BindView(R.id.txt_description)
TextViewFont txt_description;
#OnClick(R.id.linear_layout)
public void onClick() {
lastCheckedPosition = getAdapterPosition();
notifyDataSetChanged();
}
public posts(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
EndlessRecyclerViewScrollListener
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// // before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
RecyclerView.LayoutManager mLayoutManager;
public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
}
public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
}
else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
#Override
public void onScrolled(RecyclerView view, int dx, int dy) {
int lastVisibleItemPosition = 0;
int totalItemCount = mLayoutManager.getItemCount();
if (mLayoutManager instanceof StaggeredGridLayoutManager) {
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
// get maximum element within the list
lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
} else if (mLayoutManager instanceof GridLayoutManager) {
lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
} else if (mLayoutManager instanceof LinearLayoutManager) {
lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
}
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) {
this.loading = true;
}
}
// If it’s still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
// If it isn’t currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
// threshold should reflect how many total columns there are too
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
currentPage++;
onLoadMore(currentPage, totalItemCount, view);
loading = true;
}
}
// Call this method whenever performing new searches
public void resetState() {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = 0;
this.loading = true;
}
// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);
I hope you help me to found solution....
EndlessRecyclerViewScrollListener checks the last visible position with the LayoutManager. When it detects the final one (in this case), call onLoadMore() method. Something weird I notice is that you are managing page in the activity but then ignoring the currentPage value that is using the listener.
Maybe the problem is in that difference. Put a breakpoint inside the EndlessRecyclerViewScrollListener and check how many times calls ´onLoadMore()` method and with which parameters.
Hope it helps.
I haven't found yet the proper examples of how to make an app load more items from Retrofit onResponse while scrolling down the RecyclerView.
Here is how I'm loading my fist 20 items:
List<ModelPartners> model = new ArrayList<>();
Call<ResponsePartners> call = ApiClient.getRetrofit().getPartnerList(params);
call.enqueue(this);
My RecyclerView
PartnersAdapter adapter = new PartnersAdapter(getContext(), recyclerView, model);
recyclerView.setAdapter(adapter);
And here is my Retrofit onResponse:
#Override
public void onResponse(Call<ResponsePartners> call, Response<ResponsePartners> response) {
if (getActivity() != null && response.isSuccessful()) {
List<ModelPartners> body = response.body().getData();
//Rest of the code to add body to my Adapter and notifyDataSetChanged
}
}
My Problem is, every time I add the method to load more items on scroll, onResponse keeps loading non-stop till the last page. Even if I have put set loading to false.
Can someone please show how to properly use pagination in Retrofit? What libraries you used with Retrofit or show me how you did it your way? Thank you in advance
You need three things to achieve this, you need:
You need an onscroll listener for the recycler view.
You need a method to add new items to the recycler adapter
You need to call your paginated endpoint
Assuming you have a model like this from the server
public class PagedList<T> {
private int page = 0;
private List<T> results = new ArrayList<>();
private int totalResults = 0;
private int totalPages = 0;
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public List<T> getResults() {
return results;
}
public void setResults(List<T> results) {
this.results = results;
}
public int getTotalResults() {
return totalResults;
}
public void setTotalResults(int totalResults) {
this.totalResults = totalResults;
}
public int getTotalPages() {
return totalPages;
}
public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}
}
Your OnScroll Listener: -
In your activity this is what you would have, so add the second method to your activity
public void onCreate(Bundle savedInstance) {
// setup your view components
// ...
// get the layout manager
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
// rest endpoint
apiEndpoint = retrofit.create(RetrofitEndpoint.class);
// initialise loading state
mIsLoading = false;
mIsLastPage = false;
// amount of items you want to load per page
final int pageSize = 20;
// set up scroll listener
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// number of visible items
int visibleItemCount = layoutManager.getChildCount();
// number of items in layout
int totalItemCount = layoutManager.getItemCount();
// the position of first visible item
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
boolean isNotLoadingAndNotLastPage = !mIsLoading && !mIsLastPage;
// flag if number of visible items is at the last
boolean isAtLastItem = firstVisibleItemPosition + visibleItemCount >= totalItemCount;
// validate non negative values
boolean isValidFirstItem = firstVisibleItemPosition >= 0;
// validate total items are more than possible visible items
boolean totalIsMoreThanVisible = totalItemCount >= pageSize;
// flag to know whether to load more
boolean shouldLoadMore = isValidFirstItem && isAtLastItem && totalIsMoreThanVisible && isNotLoadingAndNotLastPage
if (shouldLoadMore) loadMoreItems(false);
}
});
// load the first page
loadMoreItems(true);
}
private void loadMoreItems(boolean isFirstPage) {
// change loading state
mIsLoading = true;
mCurrentPage = mCurrentPage + 1;
// update recycler adapter with next page
apiEndpoint.getPagedList(mCurrentPage).enqueue(new Callback<PagedList<Object>>() {
#Override
public void onResponse(Call<PagedList<Object>> call, Response<PagedList<Object>> response) {
PagedList<Object> result = response.body();
if (result == null) return;
else if (!isFirstPage) mAdapter.addAll(result.getResults());
else mAdapter.setList(result.getResults());
mIsLoading = false;
mIsLastPage = mCurrentPage == result.getTotalPages();
}
#Override
public void onFailure(Call<PagedList<Object>> call, Throwable t) {
Log.e("SomeActivity", t.getMessage());
}
});
}
Recycler Adapter: -
For the recycler adapter all you need is to add a method that adds items to its list, as below
public class SomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> list;
// .. other overridden members
public void setList(List<Object> list) {
this.list = list;
notifyDataSetChanged();
}
public void addAll(List<Object> newList) {
int lastIndex = list.size() - 1;
list.addAll(newList);
notifyItemRangeInserted(lastIndex, newList.size());
}
}
Then finally your retrofit interface that takes the page, as below:
interface RetrofitEndpoint {
#GET("paged/list/endpoint")
Call<PagedList<Object>> getPagedList(#Query("page") int page);
}
Hope that helps.
#Alimov Shohrukh, I also tried for many ways for Pagination
1) Check this link,This is one way
2) I mention it step by step
from API side - you need to pass pageConunt, pageIndex and get data based on above parameters
pageConunt - means how many data you want get from server for i.e - 10
pageIndex - page number for i.e 1,2,3 etc
public class DemoActivity extends BaseActivity{
List<BaseModel> orderList = new ArrayList<>();
ListAdapter listAdapter;
LinearLayoutManager layoutManager;
OrderListAdapter orderListAdapter;
int pageIndex = 1; // you can pass 1,2,3...
int pageCount = 10; //you can pass 10,20...
boolean isApiSuccess = false;
//if api get success == true then you need to work with load more sp we take one boolean variable
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
findView();
setRecyclerViewPagination();
}
private void findView() {
//recyclerview
rv_po_order_number = findViewById(R.id.rv_po_order_number);
}
//custom OnScrollListener
private RecyclerView.OnScrollListener recyclerViewOnScrollListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (isApiSuccess) {
pageIndex++;
listTestApiCall(pageIndex, searchQuery);
Log.e(TAG, pageIndex + " page count ");
orderListAdapter.showLoading(true);
rv_po_order_number.post(new Runnable() {
public void run() {
// There is no need to use notifyDataSetChanged()
orderListAdapter.notifyDataSetChanged();
}
});
}
}
};
private void setRecyclerViewPagination() {
orderList = new ArrayList<>();
orderListAdapter = new OrderListAdapter(mActivity, orderList);
layoutManager = new LinearLayoutManager(mActivity, LinearLayoutManager.VERTICAL, false);
rv_po_order_number.setLayoutManager(layoutManager);
rv_po_order_number.setHasFixedSize(true);
rv_po_order_number.setAdapter(orderListAdapter);
rv_po_order_number.addOnScrollListener(recyclerViewOnScrollListener);
listTestApiCall(pageCount,pageIndex);
}
private void listTestApiCall(final int pageCount,final int pageIndex) {
// if (CommonUtils.isConnectingToInternet(mActivity)) {
if (validateInternetConn(mActivity)) {//check internet
final boolean isFirstPage = pageIndex == 1 ? true : false;
if (isFirstPage)
//do your stuff - if you want to show loader
Call<BaseModel> call = ApiClient.getClient().listApiCall(pageCount, pageIndex);
call.enqueue(new Callback<BaseModel>() {
#Override
public void onResponse(Call<BaseModel> call, Response<BaseModel> response) {
try {
if (response.isSuccessful()) {
boolean success = response.body().getStatus();
isApiSuccess = response.body().getStatus();
if (success) {
List<BaseModel> list = new ArrayList<>();
if (response.body().getData() != null) {
list = response.body().getData();
if (isFirstPage)
orderList.clear();
orderList.addAll(response.body().getData());
}
if (list != null && list.size() > 0) {
isApiSuccess = true;
} else {
isApiSuccess = false;
}
} else if (!success) {
isApiSuccess = false;
String message = response.body().getMessage();
}
listAdapter.showLoading(false);
listAdapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
Log.e("Tag", "error=" + e.toString());
isApiSuccess = false;
}
}
#Override
public void onFailure(Call<BaseModel> call, Throwable t) {
Log.e("Tag", "error" + t.toString());
isApiSuccess = false;
}
});
}
}
}
here is OrderListAdapter
public class OrderListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
Activity mActivity;
List<OrderListBaseModel.DataBean> mList;
PurchaseOrderReceiveOnClick purchaseOrderReceiveOnClick;
DeleteUpdatePOOnClick deleteUpdatePOOnClick;
public static final int TYPE_FOOTER = 1;
public static final int TYPE_ITEM = 2;
protected boolean showLoader = true;
public OrderListAdapter(Activity mActivity, List<OrderListBaseModel.DataBean> mList, PurchaseOrderReceiveOnClick purchaseOrderReceiveOnClick,DeleteUpdatePOOnClick deleteUpdatePOOnClick) {
this.mActivity = mActivity;
this.purchaseOrderReceiveOnClick = purchaseOrderReceiveOnClick;
this.deleteUpdatePOOnClick = deleteUpdatePOOnClick;
this.mList = mList;
}
public OrderListAdapter(Activity mActivity, List<OrderListBaseModel.DataBean> mList) {
this.mActivity = mActivity;
this.mList = mList;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_ITEM) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_purchase_order_receive, parent, false);
return new DataViewHolder(v, purchaseOrderReceiveOnClick);
} else if (viewType == TYPE_FOOTER) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.loading_layout, parent, false);
return new FooterViewHolder(v);
} else
return null;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof DataViewHolder) {
final DataViewHolder dataViewHolder = (DataViewHolder) holder;
final OrderListBaseModel.DataBean dataBean = getItem(position);
if (dataBean != null) {
dataViewHolder.setPosition(position);
dataViewHolder.setSingleBean(dataBean);
}
}
}
private OrderListBaseModel.DataBean getItem(int position) {
if (mList.size() > 0)
return mList.get(position);
else
return null;
}
public void showLoading(boolean status) {
showLoader = status;
}
#Override
public int getItemViewType(int position) {
if ((position == mList.size() - 1) && showLoader) {
return TYPE_FOOTER;
}
return TYPE_ITEM;
}
public void removeItem(int position) {
mList.remove(position);
notifyItemRemoved(position);
}
#Override
public int getItemCount() {
return mList.size();
}
public static class DataViewHolder extends RecyclerView.ViewHolder {
int position;
OrderListBaseModel.DataBean dataBean;
private TextView tv_row_po_no,textViewOptions;
public DataViewHolder(View v, final PurchaseOrderReceiveOnClick purchaseOrderReceiveOnClick) {
super(v);
tv_row_po_no = v.findViewById(R.id.tv_row_po_no);
textViewOptions = v.findViewById(R.id.textViewOptions);
}
public void setPosition(int position) {
this.position = position;
}
public void setSingleBean(OrderListBaseModel.DataBean dataBean) {
this.dataBean = dataBean;
}
}
private class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(View view) {
super(view);
}
}
}
here is xml code
loading_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/linearRoot"
android:gravity="center_horizontal"
android:layout_marginTop="#dimen/_5sdp">
<com.app.trackpoint.custom_loader.MYLoader
android:layout_width="#dimen/_30sdp"
app:my_color="#color/colorAccent"
android:layout_height="#dimen/_30sdp" />
</LinearLayout>
I have been very meticulous in following this guide to implement pagination in my RecyclerView. Only difference is I'm using Retrofit to retrieve data from the API.
When I open my activity it stops after a while, and when I check Logcat, it says: IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{31a22aa position=4 id=-1, oldPos=2,... This is what my RecyclerView adapter looks like:
public class CuratedSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static int VIEW_TYPE_HEADER = 0;
private static int VIEW_TYPE_ITEM = 1;
private static int VIEW_TYPE_LOADING = 2;
private RecyclerView mRecyclerView;
private OnLoadMoreListener mOnLoadMoreListener;
private boolean isLoading;
private int visibleThreshold = 2;
private int lastVisibleItem, totalItemCount;
private List<Object> itemList;
public CuratedSectionAdapter(List<Object> itemList, RecyclerView recyclerView, LinearLayoutManager layoutManager) {
this.itemList = itemList;
this.mRecyclerView = recyclerView;
final LinearLayoutManager linearLayoutManager = layoutManager;
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener;
}
private class ItemViewHolder extends RecyclerView.ViewHolder {
RecyclerView itemRecyclerView;
CuratedSectionNestedAdapter nestedAdapter;
LinearLayoutManager layoutManager;
ItemViewHolder(View view) {
super(view);
itemRecyclerView = view.findViewById(R.id.recyclerView_nested);
layoutManager = new LinearLayoutManager(view.getContext(), LinearLayoutManager.HORIZONTAL, false);
}
}
private class HeaderViewHolder extends RecyclerView.ViewHolder {
TextView textViewHeader;
Typeface montserratMedium = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/Montserrat-Medium.ttf");
HeaderViewHolder(View view) {
super(view);
textViewHeader = view.findViewById(R.id.textView_header);
textViewHeader.setTypeface(montserratMedium);
}
}
private class LoadingViewHolder extends RecyclerView.ViewHolder {
ProgressBar progressBar;
LoadingViewHolder(View itemView) {
super(itemView);
progressBar = itemView.findViewById(R.id.progress_bar);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == VIEW_TYPE_HEADER) {
HeaderViewHolder viewHolder = (HeaderViewHolder) holder;
CuratedSectionHeader header = (CuratedSectionHeader) itemList.get(position);
viewHolder.textViewHeader.setText(header.getHeaderName());
} else if (holder.getItemViewType() == VIEW_TYPE_ITEM){
ItemViewHolder viewHolder = (ItemViewHolder) holder;
List<CuratedSectionItem> items = (List<CuratedSectionItem>) itemList.get(position);
if (viewHolder.nestedAdapter != null) {
viewHolder.nestedAdapter.setItems(items);
} else {
viewHolder.nestedAdapter = new CuratedSectionNestedAdapter(items);
viewHolder.itemRecyclerView.setLayoutManager(viewHolder.layoutManager);
viewHolder.itemRecyclerView.setAdapter(viewHolder.nestedAdapter);
}
} else if (holder.getItemViewType() == VIEW_TYPE_LOADING){
LoadingViewHolder viewHolder = (LoadingViewHolder) holder;
viewHolder.progressBar.setIndeterminate(true);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_HEADER) {
return new HeaderViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.main_explore_header_row, parent, false));
} else if (viewType == VIEW_TYPE_ITEM) {
return new ItemViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.main_explore_row, parent, false));
} else if (viewType == VIEW_TYPE_LOADING) {
return new LoadingViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_loading_item, parent, false));
}
throw new RuntimeException("Adapter " + viewType + "not found");
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public int getItemViewType(int position) {
if(isHeader(position)) {
return VIEW_TYPE_HEADER;
} else if(isLoading(position)) {
return VIEW_TYPE_LOADING;
} else {
return VIEW_TYPE_ITEM;
}
}
public boolean isHeader(int position) {
return itemList.get(position) instanceof CuratedSectionHeader;
}
public boolean isLoading(int position) {
return position > itemList.size();
}
public void setLoaded() {
isLoading = false;
}
}
It may have something to do with how I constructed LoadingViewHolder, but I think I did that one correctly. On the other hand, this is what the activity looks like:
public class ExploreFeedActivity extends Activity {
private RecyclerView recyclerView;
private CuratedSectionAdapter curatedSectionAdapter;
private LinearLayoutManager layoutManager;
private Sections curated;
int mStart = 0;
int mLimit = 2;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_explore);
curated = new Sections();
curated.loadSections(mStart, mLimit);
recyclerView = findViewById(R.id.recycler_view_main);
layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
}
private class Sections {
ArrayList<CuratedSection> sections = new ArrayList<>();
public Thread[] thread;
private Sections() {}
public void setSections(ArrayList<CuratedSection> sections) {
this.sections = sections;
}
public void setSectionStories(String sectionId, List<CuratedSectionItem> stories) {
for(CuratedSection s : sections){
if(s.id != null && s.id.equals(sectionId)) {
s.stories = stories;
}
}
}
public void loadStories(String sessionKey) {
thread = new Thread[sections.size()];
for( int s = 0; s < sections.size(); s++) {
thread[s] = new Thread(new LoadStories(sessionKey, sections.get(s)));
thread[s].start();
}
for( int f = 0; f < sections.size(); f++) {
try {
thread[f].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
curatedSectionAdapter = new CuratedSectionAdapter(this.getAdapterInfo(), recyclerView, layoutManager);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(curatedSectionAdapter);
curatedSectionAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
Log.e("haint", "Load More");
curated.sections.add(null);
curatedSectionAdapter.notifyItemInserted(curated.sections.size() - 1);
// Load more data for recyclerview
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Log.e("haint", "Load Further");
// Remove loading item
curated.sections.remove(curated.sections.size() - 1);
curatedSectionAdapter.notifyItemRemoved(curated.sections.size());
// Load data
curated.loadSections(2, 2);
curatedSectionAdapter.notifyDataSetChanged();
curatedSectionAdapter.setLoaded();
}
}, 5000);
}
});
}
public void loadSections(int start, int limit) {
swipeRefreshLayout.setRefreshing(false);
LoadSections load = new LoadSections(start, limit);
load.run();
}
public List<Object> getAdapterInfo() {
List<Object> list = new ArrayList<>();
for (int i = 0; i < sections.size(); i++) {
CuratedSection section = sections.get(i);
CuratedSectionHeader header = new CuratedSectionHeader();
header.setHeaderName(section.header);
list.add(header);
list.add(section.stories);
}
return list;
}
}
private class LoadSections implements Runnable {
int start, limit;
LoadSections(int start, int limit) {
this.start = start;
this.limit = limit;
}
#Override
public void run() {
SharedPreferences prefs = getSharedPreferences("user_session", MODE_PRIVATE);
final String sessionKey = prefs.getString("session_key", null);
Call<JsonArray> call;
call = TravelersApi.endpoint().getCuratedSections(sessionKey);
call.enqueue(new Callback<JsonArray>() {
#Override
public void onResponse(Call<JsonArray> call, Response<JsonArray> response) {
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawSections = response.body();
if(rawSections.size() == 0) {
//TODO: show placeholder
return;
}
for(int i = start; i < start+limit; i++) {
JsonObject jSection = rawSections.get(i).getAsJsonObject();
final CuratedSection section = new CuratedSection();
section.id = jSection.get("id").getAsString();
section.header = jSection.get("section_header").getAsString();
section.isShown = jSection.get("is_shown").getAsBoolean();
section.stories = new ArrayList<>();
curated.sections.add(section);
}
curated.setSections(curated.sections);
curated.loadStories(sessionKey);
}
#Override
public void onFailure(Call<JsonArray> call, Throwable t) {
Log.d("ERROR!", t.toString());
t.printStackTrace();
}
});
}
}
private class LoadStories implements Runnable {
String sessionKey;
CuratedSection section;
LoadStories(String sessionKey, CuratedSection section) {
this.sessionKey = sessionKey;
this.section = section;
}
#Override
public void run() {
Call<JsonArray> subCall;
subCall = TravelersApi.endpoint().getCuratedSectionTopics(sessionKey, section.id);
try {
Response<JsonArray> response = subCall.execute();
if(response.code() != 200) {
Toast.makeText(getApplicationContext(), "Cannot load page as of the moment.", Toast.LENGTH_SHORT).show();
return;
}
JsonArray rawStories = response.body();
if(rawStories.size() == 0) {
//TODO: show placeholder
return;
}
ArrayList<CuratedSectionItem> stories = new ArrayList<>();
for(int i = 0; i < rawStories.size(); i++) {
JsonObject jStories = rawStories.get(i).getAsJsonObject();
JSONObject temp = new JSONObject(jStories.toString());
JsonObject author = jStories.get("author").getAsJsonObject();
CuratedSectionItem story = new CuratedSectionItem();
story.title = jStories.get("title").getAsString();
story.avatar = author.get("profile_photo").getAsString();
stories.add(story);
}
section.stories = stories;
} catch (IOException e) {
Log.d("ERROR!", e.toString());
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
It's interesting to note that my RecyclerView adapter curatedSectionAdapter was instantiated in the method loadStories inside the private class Sections. I have tried moving that part to onCreate but then the activity won't display anything. I also suspect that the way I constructed the for loop in the callback in LoadSections has something to do with the crash.
i m integrate recycleview with multiple view so below is my code
public class ActivityProdcutListWithMulipleView extends AppCompatActivity {
RecyclerView mRecyclerView;
Toolbar mToolbar;
PostParseGet mPostParseGet;
AllMethods mAllMethods;
GetProductListing mGetProductListing;
RecyclerView.LayoutManager mLayoutManager;
ProgressDialog mProgressDialog;
int page = 1;
int total = 0;
int totalFeature = 0;
int totalbanner = 0;
ImageView mImageViewBack;
ArrayList<GetProductListing.ListingBlock> mListingBlocks;
ArrayList<GetProductListing.ListingBlock> mListingBlocksFeature;
ArrayList<GetProductListing.ListingBlock> mListingBlocksBanner;
ArrayList<OrderItemDemo> mOrderItemDemos = new ArrayList<OrderItemDemo>();
GridLayoutManager mLayoutManagerGrid;
DifferentRowAdapter adapter;
private Handler handler;
ArrayList<GetProductListing.ListingBlock> adapterData;
public static Activity mActivity;
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_product_list);
mListingBlocks = new ArrayList<>();
mActivity = this;
mListingBlocksFeature = new ArrayList<>();
mListingBlocksBanner = new ArrayList<>();
mRecyclerView = (RecyclerView) findViewById(R.id.recycle);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mImageViewBack = (ImageView) mToolbar.findViewById(R.id.imgBack);
WebAPIApplication.mArrayListingAllProductBlocks.clear();
mPostParseGet = new PostParseGet(ActivityProdcutListWithMulipleView.this);
mAllMethods = new AllMethods(ActivityProdcutListWithMulipleView.this);
mGetProductListing = new GetProductListing();
mLayoutManagerGrid = new GridLayoutManager(ActivityProdcutListWithMulipleView.this, 2);
mLayoutManager = new LinearLayoutManager(ActivityProdcutListWithMulipleView.this);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManagerGrid);
handler = new Handler();
adapterData = new ArrayList<>();
mRecyclerView.addOnScrollListener(new EndlessRecyclerGridOnScrollListener(mLayoutManagerGrid) {
#Override
public void onLoadMore(int current_page) {
if (WebAPIApplication.mArrayListingAllProductBlocks.size() < total) {
page++;
new getProductData(false, true).execute();
}
}
});
adapter = new DifferentRowAdapter(mOrderItemDemos);
mRecyclerView.setAdapter(adapter);
mLayoutManagerGrid.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return adapter.getItemViewType(position) == OrderItemDemo.BANNER_TYPE ? 2 : 1;
}
});
if (mAllMethods.check_Internet() == true) {
new getProductData(true, false).execute();
} else {
mAllMethods.ShowDialog(ActivityProdcutListWithMulipleView.this, "", getString(R.string.net_not_available), "OK");
}
mImageViewBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
}
public static class DifferentRowAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private boolean loading;
boolean isLoading = false, isMoreDataAvailable = true;
private List<OrderItemDemo> mList;
OnLoadMoreListener loadMoreListener;
public DifferentRowAdapter(List<OrderItemDemo> list) {
this.mList = list;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case OrderItemDemo.NORMAL_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_list_file, parent, false);
return new ProductListRow(view);
case OrderItemDemo.FEATURE_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_list_feature_file, parent, false);
return new ProductListRow(view);
case OrderItemDemo.BANNER_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_list_file, parent, false);
return new ProductListRow(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null) {
isLoading = true;
loadMoreListener.onLoadMore();
}
final OrderItemDemo object = mList.get(position);
if (object != null) {
switch (object.getmType()) {
case OrderItemDemo.NORMAL_TYPE:
((ProductListRow) holder).name.setText(object.getId() + " " + object.getTitle());
((ProductListRow) holder).price.setText(object.getType());
Picasso.with(mActivity)
.load(object.getImage())
.into(((ProductListRow) holder).mImageViewProduct);
((ProductListRow) holder).mImageViewBanner.setVisibility(View.GONE);
((ProductListRow) holder).mRelativeLayout.setVisibility(View.VISIBLE);
break;
case OrderItemDemo.FEATURE_TYPE:
((ProductListRow) holder).name.setText(object.getId() + " " + object.getTitle());
((ProductListRow) holder).price.setText(object.getType());
((ProductListRow) holder).mImageViewBanner.setVisibility(View.GONE);
((ProductListRow) holder).mRelativeLayout.setVisibility(View.VISIBLE);
Picasso.with(mActivity)
.load(object.getImage())
.into(((ProductListRow) holder).mImageViewProduct);
break;
case OrderItemDemo.BANNER_TYPE:
((ProductListRow) holder).price.setText(object.getType());
((ProductListRow) holder).mImageViewBanner.setVisibility(View.VISIBLE);
((ProductListRow) holder).mRelativeLayout.setVisibility(View.GONE);
break;
}
}
}
public void setMoreDataAvailable(boolean moreDataAvailable) {
isMoreDataAvailable = moreDataAvailable;
}
public void notifyDataChanged() {
notifyDataSetChanged();
isLoading = false;
}
interface OnLoadMoreListener {
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
#Override
public int getItemCount() {
if (mList == null)
return 0;
return mList.size();
}
#Override
public int getItemViewType(int position) {
if (mList != null) {
OrderItemDemo object = mList.get(position);
if (object != null) {
return object.getmType();
}
}
return 0;
}
}
public abstract class EndlessRecyclerGridOnScrollListener extends
RecyclerView.OnScrollListener {
public String TAG = EndlessRecyclerGridOnScrollListener.class
.getSimpleName();
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 1;
private LinearLayoutManager mLinearLayoutManager;
public EndlessRecyclerGridOnScrollListener(
GridLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
visibleThreshold = total;
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading
&& (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
current_page++;
onLoadMore(current_page);
loading = true;
}
}
public abstract void onLoadMore(int current_page);
}
public class getProductData extends AsyncTask<Void, Void, Void> {
boolean showLoading;
boolean pagination;
public getProductData(boolean showLoading, boolean page) {
this.showLoading = showLoading;
this.pagination = page;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (showLoading == true) {
mProgressDialog = ProgressDialog.show(ActivityProdcutListWithMulipleView.this, "", "Loading..");
}
}
#Override
protected Void doInBackground(Void... voids) {
mGetProductListing = (GetProductListing) mPostParseGet.getTopSearchData(mGetProductListing, page);
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (showLoading == true) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
}
}
if (mGetProductListing != null) {
try {
total = Integer.parseInt(mGetProductListing.getListing().getTotal());
if (mGetProductListing.getListing().getData().size() > 0) {
mListingBlocks = getProductBlock();
Log.e("FeatureSize", String.valueOf(mListingBlocksFeature.size()));
Log.e("BannerSize", String.valueOf(mListingBlocksBanner.size()));
for (int i = 0; i < WebAPIApplication.mArrayListingAllProductBlocks.size(); i++) {
if (WebAPIApplication.mArrayListingAllProductBlocks.get(i).getType().equalsIgnoreCase("product")) {
mOrderItemDemos.add(new OrderItemDemo(WebAPIApplication.mArrayListingAllProductBlocks.get(i).getId(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getTitle(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getType(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getMedium_image(), OrderItemDemo.NORMAL_TYPE));
} else if (WebAPIApplication.mArrayListingAllProductBlocks.get(i).getType().equalsIgnoreCase("featured")) {
mOrderItemDemos.add(new OrderItemDemo(WebAPIApplication.mArrayListingAllProductBlocks.get(i).getId(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getTitle(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getType(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getMedium_image(), OrderItemDemo.FEATURE_TYPE));
} else {
mOrderItemDemos.add(new OrderItemDemo(WebAPIApplication.mArrayListingAllProductBlocks.get(i).getId(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getTitle(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getType(), WebAPIApplication.mArrayListingAllProductBlocks.get(i).getMedium_image(), OrderItemDemo.BANNER_TYPE));
}
}
adapter = new DifferentRowAdapter(mOrderItemDemos);
if (pagination == false) {
mRecyclerView.setAdapter(adapter);
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/*Get Product data */
public ArrayList<GetProductListing.ListingBlock> getProductBlock() {
ArrayList<GetProductListing.ListingBlock> mArrayListParserLog = new ArrayList<GetProductListing.ListingBlock>();
for (int i = 0; i < mGetProductListing.getListing().getData().size(); i++) {
GetProductListing.ListingBlock mParserLog = new GetProductListing.ListingBlock();
mParserLog.setId(mGetProductListing.getListing().getData().get(i).getId());
mParserLog.setType(mGetProductListing.getListing().getData().get(i).getType());
mParserLog.setTitle(mGetProductListing.getListing().getData().get(i).getTitle());
mParserLog.setDiscountSale(mGetProductListing.getListing().getData().get(i).getDiscountSale());
mParserLog.setDiscountSelling(mGetProductListing.getListing().getData().get(i).getDiscountSelling());
mParserLog.setPrice(mGetProductListing.getListing().getData().get(i).getPrice());
mParserLog.setAupc(mGetProductListing.getListing().getData().get(i).getAupc());
mParserLog.setSale_end(mGetProductListing.getListing().getData().get(i).getSale_end());
mParserLog.setSale_start(mGetProductListing.getListing().getData().get(i).getSale_start());
mParserLog.setSelling_price(mGetProductListing.getListing().getData().get(i).getSelling_price());
mParserLog.setProduct_rating(mGetProductListing.getListing().getData().get(i).getProduct_rating());
mParserLog.setSlug(mGetProductListing.getListing().getData().get(i).getSlug());
mParserLog.setSold_out(mGetProductListing.getListing().getData().get(i).getSold_out());
mParserLog.setImage(mGetProductListing.getListing().getData().get(i).getImage());
mParserLog.setSku_id(mGetProductListing.getListing().getData().get(i).getSku_id());
mParserLog.setMedium_image(mGetProductListing.getListing().getData().get(i).getMedium_image());
mArrayListParserLog.add(mParserLog);
WebAPIApplication.mArrayListingAllProductBlocks.add(mParserLog);
}
return mArrayListParserLog;
}
}
When i run above code in first page i get proper value but when i call second page at that time first page value will append again with second page data so any idea how can i solve this ? your all suggestions are appreciable
Try arraylist.clear() before loading Updated data into ArrayList to Avoid Duplicate Values.
1.Add this Code Before Oncreate
ArrayList<GetProductListing.ListingBlock> mArrayListParserLog = new ArrayList<GetProductListing.ListingBlock>();
and remove it from getProductBlock()
Add mArrayListParserLog.clear(); with in getProductBlock() method
public ArrayList<GetProductListing.ListingBlock> getProductBlock(){
mArrayListParserLog.clear();
I want to implement load more in Recyclerview. Here is the code.
The code is from github. https://gist.github.com/ssinss/e06f12ef66c51252563e
MainActivity code:
package com.example.tatson.bila;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import com.example.tatson.bila.CardAdapter;
import com.example.tatson.bila.Config;
import com.example.tatson.bila.SuperHeroes;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener{
SwipeRefreshLayout swipeLayout;
LinearLayoutManager mLayoutManager;
// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;
private int previousTotal = 0;
int pastVisiblesItems, visibleItemCount, totalItemCount;
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem;
private int current_page = 1;
//Creating a List of superheroes
private List<SuperHeroes> listSuperHeroes;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
public String Img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
//Initializing our superheroes list
listSuperHeroes = new ArrayList<>();
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
swipeLayout.post(new Runnable() {
#Override
public void run() {
swipeLayout.setRefreshing(true);
getData();
}
}
);
recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener(linearLayoutManager) {
#Override
public void onLoadMore(int current_page) {
Log.d("End","Sucess");
}
});
}
//This method will get data from the web api
private void getData(){
//Showing a progress dialog
// final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false);
// appending offset to url
String url = Config.DATA_URL;
String url1 = url + offSet;
//Creating a json array request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url1,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Dismissing progress dialog
// loading.dismiss();
//calling method to parse json array
parseData(response);
adapter.notifyDataSetChanged();
// stopping swipe refresh
swipeLayout.setRefreshing(false);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array){
for(int i = 0; i<array.length(); i++) {
SuperHeroes superHero = new SuperHeroes();
CardAdapter car = new CardAdapter();
JSONObject json = null;
try {
json = array.getJSONObject(i);
superHero.setImageUrl(json.getString(Config.TAG_IMAGE_URL));
Img =json.getString(Config.TAG_IMAGE_URL);
superHero.setName(json.getString(Config.TAG_NAME));
superHero.setRank(json.getInt(Config.TAG_RANK));
// superHero.setRealName(json.getString(Config.TAG_REAL_NAME));
//superHero.setCreatedBy(json.getString(Config.TAG_CREATED_BY));
//superHero.setFirstAppearance(json.getString(Config.TAG_FIRST_APPEARANCE));
int rank = json.getInt("pid");
// updating offset value to highest value
if (rank >= offSet)
offSet = rank;
// ArrayList<String> powers = new ArrayList<String>();
//JSONArray jsonArray = json.getJSONArray(Config.TAG_POWERS);
/* for(int j = 0; j<jsonArray.length(); j++){
powers.add(((String) jsonArray.get(j))+"\n");
}*/
//superHero.setPowers(powers);
Log.d("test",Img);
car.setImageUrl(Img);
} catch (JSONException e) {
e.printStackTrace();
}
listSuperHeroes.add(superHero);
}
//Finally initializing our adapter
adapter = new CardAdapter(listSuperHeroes, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
#Override
public void onRefresh() {
listSuperHeroes.clear();
refreshItems();
}
void refreshItems() {
// Load items
getData();
// Load complete
onItemsLoadComplete();
}
void onItemsLoadComplete() {
// Update the adapter and notify data set changed
adapter.notifyDataSetChanged();
//Finally initializing our adapter
adapter = new CardAdapter(listSuperHeroes, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
// Stop refresh animation
}
}
EndlessRecyclerOnScrollListener class code:
package com.example.tatson.bila;
/**
* Created by Tatson on 23-11-2015.
*/
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName();
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int current_page = 1;
private LinearLayoutManager mLinearLayoutManager;
public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLinearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading ) {
// End has been reached
// Do something
current_page++;
Log.d("End", "Sucess");
onLoadMore(current_page);
loading = true;
}
}
public abstract void onLoadMore(int current_page);
}
Thank you.
I found an answer here that, I believe, is much better than most I've seen on SO and elsewhere.
The idea is simple: in onScrolled in your RecyclerView's ScrollListener, check if the last completely visible item is the last item in your data set.
if(llm.findLastCompletelyVisibleItemPosition() == data.length() -1){
//bottom of list!
loadMoreData();
}
This happens with a method in the LinearLayoutManager. Calling LinearLayoutManager#findLastCompletelyVisibleItemPosition() can comparing it to the position of the last item in your dataset let's you know when you can load more.
I haven't tried this for the GridLayoutManager.
UPDATE
LinearLayoutManager#findLastVisibleItemPosition() is a better alternative to LinearLayoutManager#findLastCompletelyVisibleItemPosition(), especially when your items are longer than the window height.
Check do you currently have items to scroll down -
if (! recyclerView.canScrollVertically(1))
If yes - load more items, for example, using HTTP client.
Full code:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (! recyclerView.canScrollVertically(1)){ //1 for down
loadMore();
}
}
});
In Kotlin you can use the below code snippet.
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if(!recyclerView.canScrollVertically(1)) {
// LOAD MORE
}
}
})
Try this....
static boolean loadmore=true;
LinearLayoutManager layoutManager = ((LinearLayoutManager)recyclerView.getLayoutManager());
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
// super.onScrolled(recyclerView, dx, dy);
int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();
if (lastVisiblePosition == recyclerView.getChildCount()) {
if (loadmore) {
loadmore = false;
method();
}
}
}
});
private void method(){
loadmore=true;
}
Adding to the accepted answer:
It's a better user experience if the scrolling doesn't stop before new data is loaded. Therefore you should load new data before the very last item is reached.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// already load new data if there are only 2 items left to scroll
if (llm.findLastCompletelyVisibleItemPosition() >= dataList.size()-3 && !alreadyLoadedAllData) {
loadNewData();
}
}
});
llm is your LinearLayoutManager and alreadyLoadedAllData.
public abstract class LoadMoreAdapter extends RecyclerView.Adapter{
private LoadMoreListner loadMoreListner;
private boolean isLoading;
int vissibleThreshold = 5;
public LoadMoreAdapter(final LoadMoreListner loadMoreListner, RecyclerView recyclerView) {
this.loadMoreListner = loadMoreListner;
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int totalItemCOunt = linearLayoutManager.getItemCount();
int lastVissibleItemPOs = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCOunt<= lastVissibleItemPOs+vissibleThreshold){
if (loadMoreListner!=null){
isLoading = true;
loadMoreListner.onLoadMore();
}
}
}
});
}
public void setLoaded(){
isLoading =false;
}
}
Your adapter will extends to this LoadmoreAdapter
public interface LoadMoreListner {
void onLoadMore();
}
And in your activity
#Override
public void onLoadMore() {
items.add(null);
nameLoadMoreAdapter.notifyItemInserted(items.size()-1);
loadNewData();
}
After populating list and here your loadnewData() will have this
items.remove(items.size()-1);
nameLoadMoreAdapter.notifyItemRemoved(items.size());
items.addAll(itemsArrayList);
nameLoadMoreAdapter.notifyItemInserted(items.size());
nameLoadMoreAdapter.setLoaded();
where itemsArrayList are of newdata
This links may help you .for load-moreRrecyclerview you need to change. and implement using
Link
or library
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by CRAFT BOX on 9/7/2016.
*/
public class RecyclerViewPositionHelper {
final RecyclerView recyclerView;
final RecyclerView.LayoutManager layoutManager;
RecyclerViewPositionHelper(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
this.layoutManager = recyclerView.getLayoutManager();
}
public static RecyclerViewPositionHelper createHelper(RecyclerView recyclerView) {
if (recyclerView == null) {
throw new NullPointerException("Recycler View is null");
}
return new RecyclerViewPositionHelper(recyclerView);
}
/**
* Returns the adapter item count.
*
* #return The total number on items in a layout manager
*/
public int getItemCount() {
return layoutManager == null ? 0 : layoutManager.getItemCount();
}
/**
* Returns the adapter position of the first visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* #return The adapter position of the first visible item or {#link RecyclerView#NO_POSITION} if
* there aren't any visible items.
*/
public int findFirstVisibleItemPosition() {
final View child = findOneVisibleChild(0, layoutManager.getChildCount(), false, true);
return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
}
/**
* Returns the adapter position of the first fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* #return The adapter position of the first fully visible item or
* {#link RecyclerView#NO_POSITION} if there aren't any visible items.
*/
public int findFirstCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(0, layoutManager.getChildCount(), true, false);
return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
}
/**
* Returns the adapter position of the last visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* #return The adapter position of the last visible view or {#link RecyclerView#NO_POSITION} if
* there aren't any visible items
*/
public int findLastVisibleItemPosition() {
final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, false, true);
return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
}
/**
* Returns the adapter position of the last fully visible view. This position does not include
* adapter changes that were dispatched after the last layout pass.
*
* #return The adapter position of the last fully visible view or
* {#link RecyclerView#NO_POSITION} if there aren't any visible items.
*/
public int findLastCompletelyVisibleItemPosition() {
final View child = findOneVisibleChild(layoutManager.getChildCount() - 1, -1, true, false);
return child == null ? RecyclerView.NO_POSITION : recyclerView.getChildAdapterPosition(child);
}
View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible,
boolean acceptPartiallyVisible) {
OrientationHelper helper;
if (layoutManager.canScrollVertically()) {
helper = OrientationHelper.createVerticalHelper(layoutManager);
} else {
helper = OrientationHelper.createHorizontalHelper(layoutManager);
}
final int start = helper.getStartAfterPadding();
final int end = helper.getEndAfterPadding();
final int next = toIndex > fromIndex ? 1 : -1;
View partiallyVisible = null;
for (int i = fromIndex; i != toIndex; i += next) {
final View child = layoutManager.getChildAt(i);
final int childStart = helper.getDecoratedStart(child);
final int childEnd = helper.getDecoratedEnd(child);
if (childStart < end && childEnd > start) {
if (completelyVisible) {
if (childStart >= start && childEnd <= end) {
return child;
} else if (acceptPartiallyVisible && partiallyVisible == null) {
partiallyVisible = child;
}
} else {
return child;
}
}
}
return partiallyVisible;
}
}
/* NearbyModel */
/**
* Created by CRAFT BOX on 8/23/2016.
*/
public class NearbyModel {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRate() {
return rate;
}
public void setRate(String rate) {
this.rate = rate;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getImage_path() {
return image_path;
}
public void setImage_path(String image_path) {
this.image_path = image_path;
}
String id;
String name;
String rate;
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
String distance;
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
String review;
String address;
public String getCategory_name() {
return category_name;
}
public void setCategory_name(String category_name) {
this.category_name = category_name;
}
String category_name;
String image_path;
public NearbyModel()
{
}
public NearbyModel(String id,String name,String rate,String distance,String review,String address,String category_name,String image_path)
{
this.id=id;
this.name=name;
this.rate=rate;
this.distance=distance;
this.review=review;
this.address=address;
this.category_name=category_name;
this.image_path=image_path;
}
}
/* My activity */
public class Search_by_shop extends Fragment {
private RecyclerView recyclerView;
ArrayList<NearbyModel> near_data;
NearAdapter adapter;
int firstVisibleItem, visibleItemCount, totalItemCount,count=0;
protected int m_PreviousTotalCount;
RecyclerViewPositionHelper mRecyclerViewHelper;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.search_by_shop_fragment, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.search_by_recycleview);
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mRecyclerViewHelper = RecyclerViewPositionHelper.createHelper(recyclerView);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mRecyclerViewHelper.getItemCount();
firstVisibleItem = mRecyclerViewHelper.findFirstVisibleItemPosition();
if (totalItemCount == 0 || adapter == null)
return;
if (m_PreviousTotalCount == totalItemCount)
{
return;
}
else
{
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
if (loadMore)
{
m_PreviousTotalCount = totalItemCount;
new GetAllrestaurant().execute();
}
}
}
});
new GetAllrestaurant().execute();
return rootView;
}
public class GetAllrestaurant extends AsyncTask<String, Void, JSONObject> {
ProgressDialog pd;
#Override
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(getActivity());
pd.setTitle("Please Wait");
pd.setMessage("Loading");
pd.setCancelable(false);
pd.show();
}
#Override
protected JSONObject doInBackground(String... strings) {
UserFunction uf = new UserFunction();
JSONObject json = uf.getAllrestaurunt();
return json;
}
#Override
protected void onPostExecute(JSONObject json) {
super.onPostExecute(json);
pd.dismiss();
try {
if (json.getInt("ack") == 1) {
JSONArray json_users = json.getJSONArray("result");
// looping through All Products
for (int i = 0; i < json_users.length(); i++) {
JSONObject c = json_users.getJSONObject(i);
String id = c.getString("id");
String name = c.getString("name");
String distance = c.getString("distance");
String category = c.getString("serving_category");
String rate = c.getString("rate");
String address = c.getString("address");
String count_review = c.getString("count_review");
String image_path = c.getString("image_path");
NearbyModel da=new NearbyModel(id,name,rate,distance,count_review,address,category,image_path);
near_data.add(da);
}
if(count==0)
{
adapter = new NearAdapter(getActivity(), near_data);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
else
{
adapter.notifyDataSetChanged();
}
if(json_users.length()==0)
{
count=0;
}
else
{
count+=json_users.length();
}
}
} catch (Exception e) {
Log.e("<-SubjectActException->", e.toString());
}
}
}
public class NearAdapter extends RecyclerView.Adapter<NearAdapter.ViewHolder> {
private ArrayList<NearbyModel> data;
private Context context;
public NearAdapter(Context context,ArrayList<NearbyModel> data) {
this.data = data;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_near_by, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
viewHolder.name.setText(data.get(i).getName());
viewHolder.distince.setText(data.get(i).getDistance());
viewHolder.review.setText(data.get(i).getReview());
viewHolder.category.setText(data.get(i).getCategory_name());
viewHolder.address.setText(data.get(i).getAddress());
viewHolder.rat.setRating(Integer.parseInt(data.get(i).getRate()));
viewHolder.vi_click.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
GlobalVariable.position=i;
Intent ik=new Intent(context,Restaurant_detail.class);
ik.putExtra("rid",""+data.get(i).getId());
startActivity(ik);
}
});
if(data.get(i).getImage_path().equals(""))
{
Picasso.with(context).load("abc").placeholder(R.drawable.load_240).into(viewHolder.img);
}
else
{
Picasso.with(context).load(data.get(i).getImage_path()).placeholder(R.drawable.load_240).into(viewHolder.img);
}
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView name,distince,review,category,address;
private ImageView img;
private RatingBar rat;
CardView vi_click;
public ViewHolder(View view) {
super(view);
name = (TextView)view.findViewById(R.id.list_near_by_name);
distince = (TextView)view.findViewById(R.id.list_near_by_distince);
review = (TextView)view.findViewById(R.id.list_near_by_review);
category = (TextView)view.findViewById(R.id.list_near_by_category);
address = (TextView)view.findViewById(R.id.list_near_by_address);
img = (ImageView) view.findViewById(R.id.list_near_by_img);
rat = (RatingBar)view.findViewById(R.id.list_near_by_ratbar);
vi_click = (CardView)view.findViewById(R.id.list_near_card);
}
}
}
You can check this link for Load More RecyclerView and Bottom ProgressBar.
I have created a commonAdapter to handle loadMore
public abstract class CommonModelAdapter<T,V extends BaseModelViewHolder<T>> extends RecyclerView.Adapter<V>{
public abstract V setViewHolder(ViewGroup parent);
private Context mContext;
private List<T> items;
private List<T> copyItems;
public static final int VIEW_TYPE_PROGRESS = 0;
public static final int VIEW_TYPE_ITEM = 1;
public CommonModelAdapter(Context mContext,List<T> items){
this.mContext = mContext;
this.items = items;
copyItems = new ArrayList<>();
copyItems.addAll(items);
}
#Override
public V onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == VIEW_TYPE_ITEM){
return setViewHolder(parent);
}
else{
return (V) new ProgressViewHolder(parent ,R.layout.item_progress_loader);
}
}
#Override
public void onBindViewHolder(V holder, int position) {
if (holder instanceof ProgressViewHolder) {
((ProgressViewHolder) holder).showProgressLoader();
}
else{
try {
holder.onBindData(items.get(position));
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public int getItemViewType(int position) {
if(items.get(position) == null)
return VIEW_TYPE_PROGRESS;
else
return VIEW_TYPE_ITEM;
}
public T getItemAt(int position){
return items.get(position);
}
public void setItems(List<T> newItems){
this.items = newItems;
}
}
Where BaseModelViewHolder
public abstract class BaseModelViewHolder<T extends BaseModelBO> extends RecyclerView.ViewHolder {
public abstract void onBindData(T data);
public BaseModelViewHolder(ViewGroup parent, int layoutId) {
super(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
}
public <T extends View> T findViewById(#IdRes int resId) {
return (T) itemView.findViewById(resId);
}
}
LoadMoreRecyclerView
public class LoadMoreRecyclerView extends RecyclerView {
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
//WrapperLinearLayout is for handling crash in RecyclerView
private WrapperLinearLayout mLayoutManager;
private Context mContext;
private OnLoadMoreListener onLoadMoreListener;
public LoadMoreRecyclerView(Context context) {
super(context);
mContext = context;
init();
}
public LoadMoreRecyclerView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
public LoadMoreRecyclerView(Context context, #Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
init();
}
private void init(){
mLayoutManager = new WrapperLinearLayout(mContext,LinearLayoutManager.VERTICAL,false);
this.setLayoutManager(mLayoutManager);
this.setItemAnimator(new DefaultItemAnimator());
this.setHasFixedSize(true);
}
#Override
public void onScrolled(int dx, int dy) {
super.onScrolled(dx, dy);
if(dy > 0) //check for scroll down
{
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if (loading)
{
if ( (visibleItemCount + pastVisiblesItems) >= totalItemCount)
{
loading = false;
Log.v("...", "Call Load More !");
if(onLoadMoreListener != null){
onLoadMoreListener.onLoadMore();
}
//Do pagination.. i.e. fetch new data
}
}
}
}
#Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
}
public void enableLoadingMore(boolean moreLoading){
loading = moreLoading;
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public void setScrolling(boolean enable){
mLayoutManager.setScrollEnabled(enable);
}
}
When you want to show progress...
mLoadMoreRecyclerView.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
{
overAllItems.add(null); //to show ProgressDialog
mAdapter.notifyDataSetChanged();
callYourService();
}
/*else{
//for reEnable calling it...
mLoadMoreRecyclerView.enableLoadingMore(true);
}*/
}
});