I've implemented a Recyclerview
in my test app. Currently I pull around 5000 items of data into a model and load my view with this list. Everything is great, and performs nicely but I don't particularly want to load all 5000 items. I would prefer to load 100 items and once the user hits the bottom, load the next 100 and essentially make it an ever growing list.
I can implement onScrollListener
against the Recyclerview
to do the detection of when I've reached the end but my issue (as simple as this sounds) is, what is the best way to tell the Recyclerview
to load only 100 until I say?
My Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<ImageFeed> mFeedList;
public MyAdapter(List<ImageFeed> feedList) {
this.mFeedList = feedList;
}
public void setFeedList(List<ImageFeed> feedList) {
mFeedList = feedList;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup vGroup, int i) {
View v = LayoutInflater.from(vGroup.getContext()).inflate(R.layout.recycler_list, vGroup, false);
return new MyAdapter.ViewHolder(v);
}
@Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, int i) {
String mTitle = mFeedList.get(i).getTitle();
...//Do other stuff
}
@Override
public int getItemCount() {
return mFeedList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected ImageView mImageView;
protected TextView mTitle;
protected ProgressBar mLoader;
private int mItemId;
public ViewHolder(View itemView) {
super(itemView);
this.mImageView = (ImageView) itemView.findViewById(R.id.imgItem);
this.mTitle = (TextView) itemView.findViewById(R.id.txtTitle);
this.mLoader = (ProgressBar) itemView.findViewById(R.id.mLoaderProgress);
this.mImageView.setOnClickListener(this);
itemView.setOnClickListener(this);
}
public void setItem(int item) {
this.mItemId = item;
}
@Override
public void onClick(View v) {
if (v instanceof ImageView) {
Toast.makeText(v.getContext(), "Image view clicked: " + this.mItemId, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(v.getContext(), this.mItemId + " ", Toast.LENGTH_SHORT).show();
}
}
}
}
Thinking the scenario out I would have thought passing a smaller list is a possibility but it doesn't feel completely right.
Select * from user LIMIT 10,20 ; every time after added the new data in arrayList call notifyDataSetChanged() to adapter of your recycler view. Save this answer. Show activity on this post.
In RecyclerView use android:nestedSrollingEnabled="false" and use NestedScrollView as a parent Scroll View. This was the only answer that worked for me - I had a ScrollView wrapping two RecyclerViews.
Try to use cardElevation=0dp. This should remove the extra spacing between recyclerview items.
If the size of ImageView in RecyclerView items is not fixed then RecyclerView will take some time to load and adjust the RecyclerView item size according to the size of Image. So to improve the performance of our RecyclerView we should keep the size of our ImageView to make it RecyclerView load faster.
Ok so this wasn't particularly difficult after all - I think my main issue was over thinking the scenario...
So the first thing I do is get the appropriate data (in this case through JSON) and store it in a JSON array for manipulation later - currently I'm still getting the full set (I.e 5000) but that's easily changeable.
This is done through an AsyncTask with an indeterminate progress bar. Once it's completed, I only parse the JSON to 20 elements and load this into the adapter.
Once done I have my Recyclerview.onScrollListener....
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mOnScreenItems = mRecyclerView.getChildCount();
mTotalItemsInList = llm.getItemCount();
mFirstVisibleItem = llm.findFirstVisibleItemPosition();
if (mLoadingItems) {
if (mTotalItemsInList > mPreviousTotal) {
mLoadingItems = false;
mPreviousTotal = mTotalItemsInList;
}
}
if (!mLoadingItems && (mTotalItemsInList - mOnScreenItems) <= (mFirstVisibleItem + mVisibleThreshold)) {
new AsyncLoadTask().execute();
mLoadingItems = true;
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
When it nears the end or hits the bottom a new AsynTask is kicked off to load additional items into the list. The onPostExecute()
then updates the adapter through its mMyAdapter.notifyDataSetChanged();
method resulting in a nice smooth update. A lot of cleaning up to do but the basics are there.
Thanks for the direction guys!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With