Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have a Recyclerview and a list with 5000 items but I only want to load 100 items at a time

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.

like image 750
Hamz4h_ Avatar asked Feb 24 '15 16:02

Hamz4h_


People also ask

How do you limit an array list to 10 and show next 10 items on click of more?

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.

How do you load all items in RecyclerView without scrolling?

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.

How do I reduce space between items in RecyclerView?

Try to use cardElevation=0dp. This should remove the extra spacing between recyclerview items.

How do you make a RecyclerView more performant?

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.


1 Answers

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!

like image 121
Hamz4h_ Avatar answered Sep 23 '22 17:09

Hamz4h_