RecyclerView for large items

Deadly 提交于 2019-12-12 02:16:30

问题


In our app we have a RecyclerView that shows large items in horizontal list. We use LinearLayoutManager to do that. The issue occurs when user scrolls the screen. When next large items needs to appear on a screen UI is frozen.

What we wanted to implement is some kind of lazy loading for RecyclerView item. So that similar to facebook's implementation user saw an stub, and once he stopped scrolling UI would update to show actual content.

The question is - what is the correct extension point for that? Should I implement custom LayoutManager? Or there are existing solutions for that?


回答1:


If you are using Xamarin as your tag say you can do this:

public class  XamarinRecyclerViewOnScrollListener : RecyclerView.OnScrollListener
{
    public delegate void LoadMoreEventHandler(object sender, EventArgs e);
    public event LoadMoreEventHandler LoadMoreEvent;

    private LinearLayoutManager LayoutManager;

    public XamarinRecyclerViewOnScrollListener (LinearLayoutManager layoutManager)
    {
        LayoutManager = layoutManager;
    }

    public override void OnScrolled (RecyclerView recyclerView, int dx, int dy)
    {
        base.OnScrolled (recyclerView, dx, dy);

        var visibleItemCount = recyclerView.ChildCount;
        var totalItemCount = recyclerView.GetAdapter().ItemCount;
        var pastVisiblesItems = LayoutManager.FindFirstVisibleItemPosition();

        if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
            LoadMoreEvent (this, null);
        }
    }
}

To use this in your view use:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var view = base.OnCreateView(inflater, container, savedInstanceState);

        var recyclerView = view.FindViewById<RecyclerView>(Resource.Id.my_recycler_view);
        if (recyclerView != null)
        {
            recyclerView.HasFixedSize = true;

            var layoutManager = new LinearLayoutManager(Activity);

            var onScrollListener = new XamarinRecyclerViewOnScrollListener (layoutManager);
            onScrollListener.LoadMoreEvent += (object sender, EventArgs e) => {
                //Load more stuff here
            };

            recyclerView.AddOnScrollListener (onScrollListener);

            recyclerView.SetLayoutManager(layoutManager);
        }
        return view;
    }



回答2:


Without seeing exactly what you're doing, I can only make a high level suggestion. And that suggestion is attaching a scroll listener to the recyclerView.

How would this work for you?

        final int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
    final int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();

    myRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            switch (newState) {
                case RecyclerView.SCROLL_STATE_IDLE:
                    for (int i = firstVisiblePosition; i <= lastVisiblePosition; i++) {
                        // start content loading here
                        recyclerView.getChildAt(i).loadMyContent;
                    }
                    break;
                case RecyclerView.SCROLL_STATE_DRAGGING:
                    for (int i = firstVisiblePosition; i <= lastVisiblePosition; i++) {
                        // cancel content loading here
                        recyclerView.getChildAt(i).cancelLoad;
                    }
                    break;
                case RecyclerView.SCROLL_STATE_SETTLING:
                    // you could load content here, but it could end up off screen by the time it stops, so I would not recommend it
                    break;
            }
        }
    });

I would like to add that if you are loading images, take a look at the Picasso library:

From Picasso's webpage:

ADAPTER DOWNLOADS

Adapter re-use is automatically detected and the previous download canceled.

@Override public void getView(int position, View convertView, ViewGroup parent) {
  SquaredImageView view = (SquaredImageView) convertView;
  if (view == null) {
    view = new SquaredImageView(context);
  }
  String url = getItem(position);

  Picasso.with(context).load(url).into(view);
}


来源:https://stackoverflow.com/questions/31816866/recyclerview-for-large-items

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!